module STLClass use IOClass use RandomClass use ArrayClass type :: STL_ real(real64), allocatable :: normal(:, :) real(real64), allocatable :: Facet(:, :, :) contains procedure, public :: open => importSTL procedure, public :: import => importSTL procedure, public :: write => exportSTL procedure, public :: export => exportSTL procedure, public :: reduceSize => reduceSizeSTL procedure, public :: reduce => reduceSizeSTL end type contains ! ###################################################### subroutine reduceSizeSTL(obj, ratio) class(STL_), intent(inout) :: obj type(STL_) :: buffer real(real64), intent(in) :: ratio ! conpression ratio (0 < ratio < 1) type(Random_) :: random integer(int32) :: final_num, n, kill_id, i, kill_num, id logical, allocatable :: kill_list(:) if (ratio > 1.0d0 .or. ratio < 0.0d0) then print *, "reduceSizeSTL :: ERROR :: please input conpression ratio (0 < ratio < 1)" return end if final_num = int(dble(size(obj%Facet, 1))*ratio) n = size(obj%Facet, 1) allocate (kill_list(n)) kill_list(:) = .false. kill_num = n - final_num print *, "Reduce number of facet from ", n, " to ", final_num, " ratio: ", ratio allocate (buffer%facet(final_num, 3, 3)) allocate (buffer%normal(final_num, 3)) buffer%facet(:, :, :) = 0.0d0 buffer%normal(:, 1:2) = 0.0d0 buffer%normal(:, 3) = 1.0d0 call random%init() i = 0 do if (i == kill_num) exit kill_id = int(dble(n)*random%random()) if (kill_id == 0) then kill_id = 1 end if if (kill_list(kill_id) .eqv. .true.) then cycle else i = i + 1 kill_list(kill_id) = .true. end if end do id = 0 do i = n, 1, -1 if (kill_list(i) .eqv. .true.) then cycle else id = id + 1 buffer%facet(id, :, :) = obj%facet(i, :, :) end if end do deallocate (obj%facet) deallocate (obj%normal) obj%facet = buffer%facet obj%normal = buffer%normal end subroutine ! ###################################################### subroutine importSTL(obj, name) class(STL_), intent(inout) :: obj character(*), intent(in) :: name character(200) :: ch character(5) ::facet character(6) ::normal real(real64) :: x, y, z integer(int32) :: numoffacet, i, j, numnorm, n type(IO_) :: f type(String_) :: string if (index(name, ".stl") == 0 .and. index(name, ".STL") == 0) then print *, "open ", name//".stl" call f%open(name//".stl") else call f%open(name) end if if (allocated(obj%normal)) deallocate (obj%normal) if (allocated(obj%facet)) deallocate (obj%facet) numoffacet = 0 do if (f%EOF .eqv. .true.) exit string = f%readline() ch = adjustl(string%all) if (index(ch, "outer") /= 0 .and. index(ch, "loop") /= 0) then numoffacet = numoffacet + 1 cycle end if end do allocate (obj%normal(numoffacet, 3)) allocate (obj%facet(numoffacet, 3, 3)) call f%close() if (index(name, ".stl") == 0 .and. index(name, ".STL") == 0) then call f%open(name//".stl") else call f%open(name) end if n = numoffacet numoffacet = 0 numnorm = 0 do if (f%EOF .eqv. .true.) exit string = f%readline() ch = adjustl(string%all) if (index(ch, "facet") /= 0 .and. index(ch, "normal") /= 0) then read (ch, *) facet, normal, x, y, z numnorm = numnorm + 1 obj%normal(numnorm, 1) = x obj%normal(numnorm, 2) = y obj%normal(numnorm, 3) = z cycle end if if (index(ch, "outer") /= 0 .and. index(ch, "loop") /= 0) then numoffacet = numoffacet + 1 do i = 1, 3 read (f%fh, *) ch, x, y, z obj%facet(numoffacet, i, 1) = x obj%facet(numoffacet, i, 2) = y obj%facet(numoffacet, i, 3) = z end do cycle cycle end if ! if(ch(1:8)=="endfacet" .or. ch(1:5)=="solid" )then ! if(numnorm==n)then ! exit ! endif ! numnorm=numnorm+1 ! read(f%fh,*) facet,normal,x,y,z ! obj%normal(numnorm,1)=x ! obj%normal(numnorm,2)=y ! obj%normal(numnorm,3)=z ! endif ! ! if( ch(1:10)=="outer" )then ! numoffacet=numoffacet+1 ! do i=1,3 ! read(f%fh,*) ch,x,y,z ! obj%facet(numoffacet,i,1)=x ! obj%facet(numoffacet,i,2)=y ! obj%facet(numoffacet,i,3)=z ! enddo ! cycle ! endif ! ! ! if( ch(1:8)=="endsolid" )then ! cycle ! endif end do call f%close() end subroutine ! ############################################################################# ! ###################################################### subroutine exportSTL(obj, name) class(STL_), intent(inout) :: obj character(*), intent(in) :: name character(200) :: ch character(5) ::facet character(6) ::normal real(real64) :: x, y, z integer(int32) :: numoffacet, i, j, numnorm, n type(IO_) :: f if (index(name, ".stl") == 0 .and. index(name, ".STL") == 0) then call f%open(name//".stl") else call f%open(name) end if write (f%fh, '(A)') "solid "//name do i = 1, size(obj%facet, 1) write (f%fh, '(A, f10.4, f10.4, f10.4)') "facet normal ", real(obj%normal(i, 1)), & real(obj%normal(i, 2)), real(obj%normal(i, 3)) write (f%fh, '(A)') "outer loop " write (f%fh, '(A, f10.4, f10.4, f10.4)') "vertex ", real(obj%facet(i, 1, 1)), real(obj%facet(i, 1, 2)), real(obj%facet(i, 1, 3)) write (f%fh, '(A, f10.4, f10.4, f10.4)') "vertex ", real(obj%facet(i, 2, 1)), real(obj%facet(i, 2, 2)), real(obj%facet(i, 2, 3)) write (f%fh, '(A, f10.4, f10.4, f10.4)') "vertex ", real(obj%facet(i, 3, 1)), real(obj%facet(i, 3, 2)), real(obj%facet(i, 3, 3)) write (f%fh, '(A)') "endloop" write (f%fh, '(A)') "endfacet" end do write (f%fh, '(A)') "endsolid "//name call f%close() end subroutine end module