indexing description: "[ Normalized 2D vector, used for directions. uses the coefficients to save the direction Please note, that on the screen, y is negative, and therefore the angles start from the right (0 radian), go down (pi/2 radian), left (pi radian) and finally top (3*pi/2 radian) ]" date: "$Date$" revision: "$Revision$" class EM_DIRECTION_2D inherit DOUBLE_MATH undefine out end ANY redefine out end create make, make_from_coefficients, make_from_direction, make_from_angle feature -- Creation make is -- creation procedure do x := 1 y := 0 end make_from_coefficients (x_coeff, y_coeff: DOUBLE) is -- creates a direction from both given coefficients do set_direction (x_coeff, y_coeff) end make_from_direction (dir: EM_DIRECTION_2D) is -- takes a direction and creates the same direction do set_direction (dir.x, dir.y) ensure direction_set: x = dir.x and y = dir.y end make_from_angle (an_angle: DOUBLE) is -- takes an angle and creates a direction from the given angle do set_angle (an_angle) end feature -- Access x: DOUBLE -- Vertical coefficient y: DOUBLE -- Horizontal coefficient feature -- Element change set_direction (x_coeff: DOUBLE; y_coeff: DOUBLE) is -- sets the direction with x and y coefficients (this normalizes the coefficients automatically) local factor: DOUBLE do if x_coeff = 0 and y_coeff = 0 then -- prevent division by zero. does not happen, if precondition is enabled x := 1 y := 0 else factor := sqrt (x_coeff*x_coeff + y_coeff*y_coeff) x := x_coeff / factor y := y_coeff / factor end end set_angle (angle_in_radian: DOUBLE) is -- sets the angle to a certain value (the attribute is given in radian) do x := cosine (angle_in_radian) y := sine (angle_in_radian) ensure x_set: x = cosine (angle_in_radian) y_set: y = sine (angle_in_radian) end add (other: EM_DIRECTION_2D) is -- adds a direction to current require direction_void: other /= void do set_angle (angle + other.angle) end feature -- Computation infix "+" (other: EM_DIRECTION_2D): EM_DIRECTION_2D is -- Sum with `other' (commutative). do create Result.make_from_angle (angle + other.angle) end feature -- Access angle: DOUBLE is -- returns the angle (in radian), computed by x and y coefficients of the direction -- WARNING: do not use, if not absolutely necessary, because of computation. -- the variables x and y have direct access, and must not be computed again from the angle do if x = 0 then if y < 0 then Result := 3*pi/2 else Result := pi/2 end elseif x < 0 then Result := pi - arc_tangent (-y/x) else if y > 0 then Result := arc_tangent (y/x) else Result := 2 * pi - arc_tangent (-y/x) end end end feature -- Output out: STRING is -- Textual representation do Result := angle.out + " rad" end feature -- Computation to_vector: EM_VECTOR_2D is -- returns the equivalend EM_VECTOR_2D do create Result.make (x, y) end feature -- Constants eps: DOUBLE is 0.001 invariant is_normalized: (x*x + y*y) > 1 - eps and x*x+y*y < 1 + eps angle_in_range: angle >= 0 and angle <= 2*pi end