indexing description: "Objects that ..." author: "" date: "$Date$" revision: "$Revision$" class EM_2D_VORONOI inherit EM_2D_PROCEDURE EM_VORONOI DOUBLE_MATH export {NONE} all end create make feature evaluate_at(eval_at: EM_VECTOR2D): DOUBLE is -- evaluate the voronoi procedure at (x,y) do compute_voronoi (eval_at.x, eval_at.y) Result := distances.item (order) end feature set_repeat_at(a_repeat: EM_VECTOR2I) 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 do repeat := a_repeat ensure repeat_set: repeat = a_repeat end repeat: EM_VECTOR2I compute_voronoi (an_x, an_y: DOUBLE) is -- compute voronoi for 'an_x', 'an_y', 'a_z' -- Values will be available in distances[order] local int_x, int_y: INTEGER fraq_x, fraq_y: DOUBLE i, j: INTEGER do -- TODO: allow to calculate modulo -- (modulo has to be octave dependent) 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 fraq_x := an_x - int_x fraq_y := an_y - int_y from i := -1 until i > 1 loop from j := -1 until j > 1 loop add_samples(fraq_x - i, fraq_y - j, modulo(int_x + i, repeat.x) , modulo(int_y + j, repeat.y)) 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: DOUBLE; int_x, int_y: INTEGER) is -- add samples to 'last_F' local dx, dy: DOUBLE fx, fy: DOUBLE dist: DOUBLE tmp: DOUBLE i, j: INTEGER count: INTEGER seed: INTEGER do seed := (int_x + permute(int_y)) 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)) dx := fx - an_x dy := fy - an_y if (manhatten_metric) then dist := ((dx.abs + dy.abs)).min(1.0) else dist := (sqrt ((dx*dx + dy*dy))).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