Faces given as a grid of points (3, nu, nv): quadrilaterals between
neighbours (two triangles each), joined around if closed_u (the last
point i to the first, for each j; e.g. a tube's circumference) or
closed_v. The edges: the grid's lines, those of constant i (along j)
every lines(1) and of constant j (along i) every lines(2) (default:
every one; 0 for none).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(Polyhedron), | intent(inout) | :: | self | |||
| real(kind=wp), | intent(in) | :: | points(:,:,:) |
(3, nu, nv), frame coordinates |
||
| logical, | intent(in), | optional | :: | closed_u |
joined around in i, in j (default false) |
|
| logical, | intent(in), | optional | :: | closed_v |
joined around in i, in j (default false) |
|
| integer, | intent(in), | optional | :: | lines(2) |
edges every lines(1) in i, lines(2) in j (default 1; 0: none) |
subroutine set_grid(self, points, closed_u, closed_v, lines) class(Polyhedron), intent(inout) :: self real(wp), intent(in) :: points(:,:,:) !! (3, nu, nv), frame coordinates logical, intent(in), optional :: closed_u, closed_v !! joined around in i, in j (default false) integer, intent(in), optional :: lines(2) !! edges every lines(1) in i, lines(2) in j (default 1; 0: none) integer :: nu, nv, mu, mv, i, j, i2, j2, nt, ne, every(2) logical :: cu, cv nu = size(points, 2) nv = size(points, 3) cu = .false. cv = .false. if (present(closed_u)) cu = closed_u .and. nu > 2 if (present(closed_v)) cv = closed_v .and. nv > 2 every = 1 if (present(lines)) every = max(lines, 0) self%v = reshape(points, [3, nu * nv]) mu = merge(nu, nu - 1, cu) ! quadrilaterals along i, j mv = merge(nv, nv - 1, cv) if (allocated(self%tri)) deallocate(self%tri) allocate(self%tri(3, 2 * max(mu, 0) * max(mv, 0))) nt = 0 do j = 1, mv j2 = modulo(j, nv) + 1 do i = 1, mu i2 = modulo(i, nu) + 1 self%tri(:, nt + 1) = [at(i, j), at(i2, j), at(i2, j2)] self%tri(:, nt + 2) = [at(i, j), at(i2, j2), at(i, j2)] nt = nt + 2 end do end do if (allocated(self%edge)) deallocate(self%edge) allocate(self%edge(2, nu * nv * 2)) ne = 0 if (every(1) > 0) then ! lines of constant i, along j do i = 1, nu if (.not. shown_line(i, nu, every(1), cu)) cycle do j = 1, mv ne = ne + 1 self%edge(:, ne) = [at(i, j), at(i, modulo(j, nv) + 1)] end do end do end if if (every(2) > 0) then ! lines of constant j, along i do j = 1, nv if (.not. shown_line(j, nv, every(2), cv)) cycle do i = 1, mu ne = ne + 1 self%edge(:, ne) = [at(i, j), at(modulo(i, nu) + 1, j)] end do end do end if self%edge = self%edge(:, 1:ne) call drop_colors(self) call make_polyhedron(self) contains pure integer function at(i_, j_) integer, intent(in) :: i_, j_ !! grid indices at = i_ + (j_ - 1) * nu end function at !> Line k of n drawn, every `step` (and the last, if the grid is open). pure logical function shown_line(k, n, step, closed) integer, intent(in) :: k, n, step !! the line, number of lines, and spacing logical, intent(in) :: closed !! the grid is joined around (else the last line drawn too) shown_line = modulo(k - 1, step) == 0 .or. (k == n .and. .not. closed) end function shown_line end subroutine set_grid