generate_circle Subroutine

private subroutine generate_circle(me, c, radius, n, nc, add_circle, circle, initial_vector, cw)

Generate the points in a circle, and optionally add it as a plate.

Type Bound

stl_file

Arguments

Type IntentOptional Attributes Name
class(stl_file), intent(inout) :: me
real(kind=wp), intent(in), dimension(3) :: c

center of the circle

real(kind=wp), intent(in) :: radius

radius of the cylinder

real(kind=wp), intent(in), dimension(3) :: n

normal vector to the circle

integer, intent(in) :: nc

number of points on the circle (must be at least 3)

logical, intent(in) :: add_circle

to also add to the circle as a plate

real(kind=wp), intent(out), dimension(:,:), allocatable :: circle

points on the circle

real(kind=wp), intent(in), optional, dimension(3) :: initial_vector

vector to use to generate the initial circle (x_unit by default)

logical, intent(in), optional :: cw

generate the points in the clockwise direction abound n (default is false)


Calls

proc~~generate_circle~~CallsGraph proc~generate_circle stl_file%generate_circle proc~add_plate stl_file%add_plate proc~generate_circle->proc~add_plate proc~axis_angle_rotation axis_angle_rotation proc~generate_circle->proc~axis_angle_rotation proc~perpendicular perpendicular proc~generate_circle->proc~perpendicular proc~unit unit proc~generate_circle->proc~unit proc~vector_projection_on_plane vector_projection_on_plane proc~generate_circle->proc~vector_projection_on_plane proc~axis_angle_rotation->proc~unit proc~cross cross proc~axis_angle_rotation->proc~cross proc~perpendicular->proc~unit proc~vector_projection vector_projection proc~vector_projection_on_plane->proc~vector_projection

Called by

proc~~generate_circle~~CalledByGraph proc~generate_circle stl_file%generate_circle proc~add_cone stl_file%add_cone proc~add_cone->proc~generate_circle proc~add_cylinder stl_file%add_cylinder proc~add_cylinder->proc~generate_circle proc~add_arrow stl_file%add_arrow proc~add_arrow->proc~add_cone proc~add_arrow->proc~add_cylinder proc~add_curve stl_file%add_curve proc~add_curve->proc~add_cylinder proc~add_axes stl_file%add_axes proc~add_axes->proc~add_arrow

Source Code

    subroutine generate_circle(me,c,radius,n,nc,add_circle,circle,initial_vector,cw)

    implicit none

    class(stl_file),intent(inout)                   :: me
    real(wp),dimension(3),intent(in)                :: c              !! center of the circle
    real(wp),intent(in)                             :: radius         !! radius of the cylinder
    real(wp),dimension(3),intent(in)                :: n              !! normal vector to the circle
    integer,intent(in)                              :: nc             !! number of points on the circle
                                                                      !! (must be at least 3)
    logical,intent(in)                              :: add_circle     !! to also add to the circle as a plate
    real(wp),dimension(:,:),allocatable,intent(out) :: circle         !! points on the circle
    real(wp),dimension(3),intent(in),optional       :: initial_vector !! vector to use to generate the initial
                                                                      !! circle (x_unit by default)
    logical,intent(in),optional                     :: cw             !! generate the points in the clockwise
                                                                      !! direction abound n (default is false)

    real(wp),dimension(3) :: v      !! initial vector for the circle
    integer               :: i      !! counter
    real(wp)              :: factor !! cw/ccw factor
    logical               :: compute_initial_vector !! if we need to compute an initial vector

    if (nc<3) error stop 'number of points on a circle must be at least 3'

    allocate(circle(3,nc))
    ! circle = -999

    factor = one
    if (present(cw)) then
        if (cw) factor = -one
    end if

    if (present(initial_vector)) then
        compute_initial_vector =  all(initial_vector==zero)
    else
        compute_initial_vector = .true.
    end if

    ! start with an initial vector on the circle (perpendicular to n0)
    ! [project x to circle (or y if x is parallel to n)]
    if (.not. compute_initial_vector) then
        v = unit(vector_projection_on_plane(initial_vector,n))
        if (.not. perpendicular(v, n) .or. all(v==zero)) then
            ! fall back to x or y axis
            v = unit(vector_projection_on_plane(x_unit,n))
            if (.not. perpendicular(v, n) .or. all(v==zero)) then
                v = unit(vector_projection_on_plane(y_unit,n))
            end if
        end if
    else
        v = unit(vector_projection_on_plane(x_unit,n))
        if (.not. perpendicular(v, n) .or. all(v==zero)) then
            v = unit(vector_projection_on_plane(y_unit,n))
        end if
    end if
    v = radius * unit(v)

    ! generate the points by rotating the initial vector around the circle:
    circle(:,1) = c + v
    do i = 2, nc
        circle(:,i) = c + axis_angle_rotation(v,n,(i-1)*factor*(360.0_wp/nc))
        if (add_circle) then
            ! draw the initial cap
            call me%add_plate(c,circle(:,i),circle(:,i-1))
        end if
    end do
    ! final plate that connects last to first
    if (add_circle) call me%add_plate(c,circle(:,1),circle(:,nc))

    end subroutine generate_circle