1. A first surface
The tutorial puts a body into a simulation grid. The body is dragon.stl, a binary STL of 6588 facets. The first program loads it, reads what FOSSIL computed on loading, and writes it back as ASCII.
use fossil, only : surface_stl_object
use penf, only : I4P, R8P
use vecfor, only : vector_R8P
implicit none
type(surface_stl_object) :: surface
type(vector_R8P) :: bmin, bmax
call surface%load_from_file(file_name='dragon.stl', guess_format=.true.) ! analyze runs insideuse fossilgives the four public types (surface_stl_object,facet_object,distance_field_object,curve_object) and the named constants. Kinds come from PENF (I4P,R8P), vectors from VecFor (vector_R8P).load_from_file(file_name=, guess_format=.true.)reads an ASCII or a binary STL: withguess_formatthe format is detected from the file size. Without it the file is read as ASCII unlessis_ascii=.false.. The optionalstatusisSTATUS_FILE_NOT_FOUNDfor a missing file andSTATUS_INVALID_INPUTfor NaN or Inf coordinates.- Loading runs
analyze: bounding box, volume, centroid, facet connectivity, the AABB tree (a SAH BVH by default) and the pseudo-normals the signed distance needs. Every later query relies on it.
bmin = surface%get_bmin() ; bmax = surface%get_bmax()
print '(A,I0)', 'facets ', surface%get_facets_number()
print '(A,3F10.4)', 'box min ', bmin%x, bmin%y, bmin%z
print '(A,3F10.4)', 'box max ', bmax%x, bmax%y, bmax%z
print '(A,F12.4)', 'volume ', surface%get_volume()
print '(A,L1,A,L1)', 'watertight ', surface%is_watertight(), ' manifold ', surface%is_manifold()- The components of
surface_stl_objectare private. They are read through accessors:get_facets_number,get_bmin,get_bmax,get_volume,get_centroid,get_non_manifold_edges_number, andfacet_at(i)for one facet. is_watertight()is true when every edge has exactly two facets,is_manifold()when the surface is also free of edges with three or more facets. The dragon is neither: as it comes, it is not a closed surface. Chapter 2 repairs what can be repaired.
call surface%save_into_file(file_name='dragon-ascii.stl', is_ascii=.true.)
print '(A)', 'saved dragon-ascii.stl'save_into_file(file_name=, is_ascii=)writes the surface, as ASCII by default (is_ascii=.false.writes binary).statusreportsSTATUS_FILE_OPEN_FAILwhen the file cannot be created.
Several solids in one file
An ASCII STL can hold several solid <name> … endsolid blocks: exporters write one per boundary condition (wall, inlet, outlet). load_from_file keeps them as named patches (get_patches_number, patch_name, facet_patch), and save_into_file writes them back as blocks; load_from_files reads one file per patch. See the cookbook recipe wall, inlet and outlet from one STL.
Running it
$ tut01_first_surface
facets 6588
box min -10.8287 -4.1883 5.2821
box max 9.6461 4.9512 19.7413
volume 465.9287
watertight F manifold F
saved dragon-ascii.stlWhat you learned
load_from_file reads an STL and analyzes it; accessors and the validity predicates tell what kind of surface you have. Reference: surface_stl_object.
Next: 2. Repairing the surface.