Skip to content

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: status is then STATUS_AMBIGUOUS_ARGS (without status the program stops). The centre of the bounding box is used here, not get_centroid(): the centroid is a volume integral, meaningful only on a closed surface.
  • rotate(axis=, angle=) turns the facets by angle radians about axis, through the origin; center= pivots about another point. rotate(matrix=) takes a rotation matrix instead.
  • resize(x=, y=, z=) (or factor=, a vector) scales about the origin, or about the centroid with respect_centroid=.true..
  • The transformations move the facets and nothing else: bounding box, volume and AABB tree are stale until analyze runs. Call it after the last transformation and before any query.
  • save_into_file writes dragon-placed.stl, the body of chapters 4 to 12.

the repaired dragon translated so that the centre of its bounding box is the origin, still in CAD units: it lies along x, the x and y edges of its box marked

the same dragon after a quarter turn about z and resize: it lies along y, longest side 1, inside the domain cube from -0.6 to 0.6

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. With remainder= 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 of other and analyzes the result.

clip keeps the facets that overlap the box y at most 0, the head half of the dragon, drawn solid inside the clip box; the remainder, the tail half, is a translucent ghost

the clipped half in stone and its mirror image through the plane y = 0 in ember, the two halves merge_solids joins

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.