indexing description: "Objects that ..." author: "" date: "$Date$" revision: "$Revision$" class EM_3D_VORONOI inherit EM_3D_PROCEDURE EM_VORONOI DOUBLE_MATH export {NONE} all end create make feature evaluate_at(pos: EM_VECTOR3D): DOUBLE is -- evaluate the voronoi procedure at (x,y) do compute_voronoi (pos.x, pos.y, pos.z) Result := distances.item (order) end feature set_repeat_at(a_repeat: EM_VECTOR3I) is -- repeat perlin noise after -- x in x-direction and after -- y in y-direction -- If x or y are 0, then the procedure isn't repeated in this direction require valid_x: a_repeat.x >= 0 valid_y: a_repeat.y >= 0 valid_z: a_repeat.z >= 0 do repeat := a_repeat end repeat: EM_VECTOR3I compute_voronoi (an_x, an_y, a_z: DOUBLE) is -- compute voronoi for 'an_x', 'an_y', 'a_z' -- Values will be available in distances[order] local int_x, int_y, int_z: INTEGER fraq_x, fraq_y, fraq_z: DOUBLE i, j, k: INTEGER do if distances = void or else distances.count /= order then create distances.make (1, order) end from i := 1 until i > distances.count loop distances.put ({INTEGER}.max_value, i) i := i + 1 end int_x := (an_x).floor int_y := (an_y).floor int_z := (a_z).floor fraq_x := an_x - int_x fraq_y := an_y - int_y fraq_z := a_z - int_z from i := -1 until i > 1 loop from j := -1 until j > 1 loop from k := -1 until k < 1 loop add_samples(fraq_x - i, fraq_y - j, fraq_z - k, modulo(int_x + i, repeat.x), modulo(int_y + j, repeat.y), modulo(int_z + k, repeat.z)) k := k + 1 end j := j + 1 end i := i + 1 end from i := 1 until i > distances.count loop if distances.item(i) > 1.0 then distances.put (1.0, i) end i := i + 1 end ensure distances_filled: distances /= void and then distances.count = order end add_samples (an_x, an_y, a_z: DOUBLE; int_x, int_y, int_z: INTEGER) is -- add samples to 'last_F' local dx, dy, dz: DOUBLE fx, fy, fz: DOUBLE dist: DOUBLE tmp: DOUBLE i, j: INTEGER inserted: BOOLEAN count: INTEGER seed: INTEGER do seed := (int_x + permute(int_y + permute(int_z))) count := poisson_count.item (seed \\ poisson_count.count + 1) count := (count * max_points_factor).floor from i := 1 until i > count loop -- Remark: I need an additional number, because without it -- the diagonal is clearly visible as x=y fx := get_random (3 + permute(seed) + permute(int_x) + permute(i)) fy := get_random (7 + permute(seed) + permute(int_y) + permute(i)) fz := get_random (9 + permute(seed) + permute(int_z) + permute(i)) dx := fx - an_x dy := fy - an_y dz := fz - a_z if (manhatten_metric) then dist := ((dx.abs + dy.abs + dz.abs)).min(1.0) else dist := (sqrt ((dx*dx + dy*dy + dz*dz))).min (1.0) end -- Insert distance into array if dist < distances.item (order) then distances.put (dist, distances.count) -- let it bubble down from j := distances.count until j <= 1 or else dist > distances.item (j - 1) loop tmp := distances.item(j - 1) distances.put (dist, j - 1) distances.put (tmp, j) j := j - 1 end end i := i + 1 end end feature {NONE} end