fplot 1.7.1
A Fortran library providing a convenient interface for plotting with Gnuplot.
Loading...
Searching...
No Matches
fplot_triangulations_delaunay_2d.f90
1submodule(fplot_core) fplot_triangulations_delaunay_2d
2 use geompack
3contains
4! ------------------------------------------------------------------------------
5 module subroutine d2d_init(this, x, y, err)
6 ! Arguments
7 class(delaunay_tri_2d), intent(inout) :: this
8 real(real64), intent(in), dimension(:) :: x, y
9 class(errors), intent(inout), target, optional :: err
10
11 ! Local Variables
12 class(errors), pointer :: errmgr
13 type(errors), target :: deferr
14 character(len = 256) :: errmsg
15 integer(int32) :: i, npts, ntri, flag
16 real(real64), allocatable, dimension(:,:) :: nodexy
17 integer(int32), allocatable, dimension(:,:) :: trinode, trinbr
18
19 ! Initialization
20 if (present(err)) then
21 errmgr => err
22 else
23 errmgr => deferr
24 end if
25 npts = size(x)
26
27 ! Input Check
28 if (size(y) /= npts) then
29 write(errmsg, 200) &
30 "Expected the y-coordinate array to have ", npts, &
31 " elements, but found ", size(y), " instead."
32 call errmgr%report_error("d2d_init", trim(errmsg), &
33 plot_array_size_mismatch_error)
34 return
35 end if
36
37 ! Clean up incase of an existing triangulation
38 if (allocated(this%m_x)) deallocate(this%m_x)
39 if (allocated(this%m_y)) deallocate(this%m_y)
40 if (allocated(this%m_indices)) deallocate(this%m_indices)
41
42 ! Allocate workspace arrays for the triangulation
43 allocate(nodexy(2, npts), stat = flag)
44 if (flag == 0) allocate(trinode(3, 2 * npts), stat = flag)
45 if (flag == 0) allocate(trinbr(3, 2 * npts), stat = flag)
46 if (flag /= 0) go to 100
47
48 ! Generate the points list
49 do i = 1, npts
50 nodexy(1,i) = x(i)
51 nodexy(2,i) = y(i)
52 end do
53
54 ! Compute the triangulation
55 call r8tris2(npts, nodexy, ntri, trinode, trinbr)
56
57 ! Populate the remainder of the object
58 allocate(this%m_x(npts), stat = flag)
59 if (flag == 0) allocate(this%m_y(npts), stat = flag)
60 if (flag == 0) allocate(this%m_indices(ntri, 3), stat = flag)
61
62 do i = 1, npts
63 this%m_x(i) = nodexy(1,i)
64 this%m_y(i) = nodexy(2, i)
65 end do
66
67 do i = 1, ntri
68 this%m_indices(i,:) = trinode(:,i)
69 end do
70
71 ! End
72 return
73
74 ! Memory Error Handler
75 100 continue
76 call errmgr%report_error("d2d_init", "Insufficient memory available.", &
77 plot_out_of_memory_error)
78 return
79
80200 format(a, i0, a, i0, a)
81 end subroutine
82
83! ------------------------------------------------------------------------------
84 pure module function d2d_get_pt_count(this) result(rst)
85 class(delaunay_tri_2d), intent(in) :: this
86 integer(int32) :: rst
87 if (allocated(this%m_x)) then
88 rst = size(this%m_x)
89 else
90 rst = 0
91 end if
92 end function
93
94! ------------------------------------------------------------------------------
95 pure module function d2d_get_tri_count(this) result(rst)
96 class(delaunay_tri_2d), intent(in) :: this
97 integer(int32) :: rst
98 if (allocated(this%m_indices)) then
99 rst = size(this%m_indices, 1)
100 else
101 rst = 0
102 end if
103 end function
104
105! ------------------------------------------------------------------------------
106 pure module function d2d_get_x_pts(this) result(rst)
107 class(delaunay_tri_2d), intent(in) :: this
108 real(real64), allocatable, dimension(:) :: rst
109 if (allocated(this%m_x)) then
110 rst = this%m_x
111 else
112 allocate(rst(0))
113 end if
114 end function
115
116! ------------------------------------------------------------------------------
117 pure module function d2d_get_y_pts(this) result(rst)
118 class(delaunay_tri_2d), intent(in) :: this
119 real(real64), allocatable, dimension(:) :: rst
120 if (allocated(this%m_y)) then
121 rst = this%m_y
122 else
123 allocate(rst(0))
124 end if
125 end function
126
127! ------------------------------------------------------------------------------
128 pure module function d2d_get_tris(this) result(rst)
129 class(delaunay_tri_2d), intent(in) :: this
130 integer(int32), allocatable, dimension(:,:) :: rst
131 if (allocated(this%m_indices)) then
132 rst = this%m_indices
133 else
134 allocate(rst(0, 0))
135 end if
136 end function
137
138! ------------------------------------------------------------------------------
139 pure module function d2d_get_tri_with_pt(this, x, y) result(rst)
140 ! Arguments
141 class(delaunay_tri_2d), intent(in) :: this
142 real(real64), intent(in) :: x, y
143 integer(int32) :: rst
144
145 ! Local Variables
146 integer(int32) :: i, j
147 real(real64) :: x1, y1, x2, y2, x3, y3
148 logical :: check
149
150 ! Initialization
151 rst = -1
152
153 ! Process
154 do i = 1, this%get_triangle_count()
155 j = this%m_indices(i, 1)
156 x1 = this%m_x(j)
157 y1 = this%m_y(j)
158
159 j = this%m_indices(i, 2)
160 x2 = this%m_x(j)
161 y2 = this%m_y(j)
162
163 j = this%m_indices(i, 3)
164 x3 = this%m_x(j)
165 y3 = this%m_y(j)
166
167 check = point_inside_triangle(x1, y1, x2, y2, x3, y3, x, y)
168 if (check) then
169 rst = i
170 end if
171 end do
172 end function
173
174! ------------------------------------------------------------------------------
175 ! Determine if a point lies within a triangle.
176 ! https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
177 ! https://en.wikipedia.org/wiki/Barycentric_coordinate_system
178 pure elemental function point_inside_triangle(x1, y1, x2, y2, x3, y3, &
179 x, y) result(rst)
180 ! Arguments
181 real(real64), intent(in) :: x1, y1, x2, y2, x3, y3, x, y
182 logical :: rst
183
184 ! Local Variables
185 real(real64) :: lambda1, lambda2, dT
186
187 ! Initialization
188 dt = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)
189 lambda1 = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / dt
190 lambda2 = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / dt
191
192 ! The point is within the triangle if:
193 ! 0 <= lambda1 <= 1
194 ! 0 <= lambda2 <= 1
195 ! 0 <= lambda1 + lambda2 <= 1
196 rst = (lambda1 <= 1.0d0 .and. lambda1 >= 0.0d0) .and. &
197 (lambda2 <= 1.0d0 .and. lambda2 >= 0.0d0) .and. &
198 (lambda1 + lambda2 >= 0.0d0 .and. lambda1 + lambda2 <= 1.0d0)
199 end function
200
201! ------------------------------------------------------------------------------
202end submodule
fplot_core