3. Placing the body
The repaired dragon is in its own CAD units, about 20 long. The simulation domain of the next chapters is the cube [-0.6, 0.6]³, so the dragon is centred, turned and scaled to a longest side of 1, then saved for the chapters that follow. Clipping, mirroring and merging close the chapter.
f90
use fossil, only : surface_stl_object
use penf, only : I4P, R8P
use vecfor, only : vector_R8P, ex_R8P, ey_R8P, ez_R8P
implicit none
real(R8P), parameter :: pi = 4._R8P * atan(1._R8P)
type(surface_stl_object) :: surface, half, rest, twin
type(vector_R8P) :: bmin, bmax
real(R8P) :: scale
call surface%load_from_file(file_name='dragon-clean.stl', guess_format=.true.)
bmin = surface%get_bmin() ; bmax = surface%get_bmax()
call surface%translate(delta=-0.5_R8P * (bmin + bmax)) ! box centre to the origin
call surface%rotate(axis=ez_R8P, angle=pi / 2._R8P) ! a quarter turn about z
call surface%analyze ! rebuild box, volume, tree
bmin = surface%get_bmin() ; bmax = surface%get_bmax()
scale = 1._R8P / maxval([bmax%x - bmin%x, bmax%y - bmin%y, bmax%z - bmin%z])
call surface%resize(x=scale, y=scale, z=scale) ! longest side 1, about the origin
call surface%analyze
bmin = surface%get_bmin() ; bmax = surface%get_bmax()
print '(A,3F9.4)', 'box min ', bmin%x, bmin%y, bmin%z
print '(A,3F9.4)', 'box max ', bmax%x, bmax%y, bmax%z
print '(A,F9.6)', 'volume ', surface%get_volume()
call surface%save_into_file(file_name='dragon-placed.stl')translate(delta=)moves every facet by a vector;x=,y=,z=give the components one by one. Passing both forms is ambiguous:statusis thenSTATUS_AMBIGUOUS_ARGS(withoutstatusthe program stops). The centre of the bounding box is used here, notget_centroid(): the centroid is a volume integral, meaningful only on a closed surface.rotate(axis=, angle=)turns the facets byangleradians aboutaxis, through the origin;center=pivots about another point.rotate(matrix=)takes a rotation matrix instead.resize(x=, y=, z=)(orfactor=, a vector) scales about the origin, or about the centroid withrespect_centroid=.true..- The transformations move the facets and nothing else: bounding box, volume and AABB tree are stale until
analyzeruns. Call it after the last transformation and before any query. save_into_filewritesdragon-placed.stl, the body of chapters 4 to 12.
f90
half = surface
call half%clip(bmin=bmin, bmax=bmax%x * ex_R8P + 0._R8P * ey_R8P + bmax%z * ez_R8P, remainder=rest)
print '(A,I0,A,I0)', 'clip y<=0 ', half%get_facets_number(), ' facets, remainder ', rest%get_facets_number()clip(bmin=, bmax=)keeps the facets that overlap the box and drops the others, whole: no facet is cut. Withremainder=the dropped facets go into a second surface, so the two parts add up to the original. Both are analyzed.
f90
twin = half
call twin%mirror(normal=ey_R8P) ! reflect through the plane y = 0
call twin%analyze
call half%merge_solids(other=twin) ! merge_solids analyzes
print '(A,I0,A)', 'merged ', half%get_facets_number(), ' facets (half + mirrored half)'mirror(normal=)reflects the facets through the plane through the origin with that normal (mirror(matrix=)takes the matrix). The facet winding is kept outward.merge_solids(other=)appends the facets ofotherand analyzes the result.
Running it
$ tut03_manipulation
box min -0.2232 -0.5000 -0.3531
box max 0.2232 0.5000 0.3531
volume 0.054283
clip y<=0 3738 facets, remainder 2848
merged 7476 facets (half + mirrored half)The placed dragon spans [-0.2232, 0.2232] × [-0.5, 0.5] × [-0.3531, 0.3531], with volume 0.054283. The clip keeps 3738 facets, the remainder has 2848: together the 6586 facets of chapter 2.
What you learned
translate, rotate, resize and mirror move facets; analyze brings the derived data up to date; clip and merge_solids split and join surfaces. Reference: surface_stl_object.
Next: 4. Signed distance.