note description: "[ An EV_FIGURE_ELLIPTIC is defined by pa and pb and not rotatable. If you need a rotatable elliptic use a EV_FIGURE_ROTATED_ELLIPTIC but if not elliptic is a lot faster. pa----------- | | | | | center | | | | | ----------- pb radius1 is half horizontal distance between pa and pb. radius2 is half vertical distance between pa and pb. ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date: 2013-04-25 18:08:32 -0400 (Thu, 25 Apr 2013) $" revision: "$Revision: 33 $" deferred class EV_MODEL_ELLIPTIC inherit EV_MODEL_ATOMIC export {ANY} Pi undefine point_count redefine default_create, bounding_box end EV_MODEL_DOUBLE_POINTED undefine default_create end feature {NONE} -- Initialization default_create -- Create a EV_FIGURE_ELLIPTIC at (0,0) with no dimension. do Precursor {EV_MODEL_ATOMIC} create point_array.make_empty (2) point_array.extend (create {EV_COORDINATE}.make (0, 0)) point_array.extend (create {EV_COORDINATE}.make (0, 0)) is_center_valid := True end feature -- Access angle: DOUBLE = 0.0 -- Since not rotatable. is_scalable: BOOLEAN -- Elliptic is scalable. do Result := True end is_rotatable: BOOLEAN -- Elliptic is not rotatable. -- (Use a rotatable_elliptic) do -- jjj Result := False Result := True end is_transformable: BOOLEAN -- Elliptic is not transformable. do -- jjj Result := False Result := True end radius1: INTEGER -- The horizontal radius. local l_point_array: like point_array p0, p1: EV_COORDINATE do l_point_array := point_array p0 := l_point_array.item (0) p1 := l_point_array.item (1) Result := as_integer ((p0.x_precise - p1.x_precise) / 2).abs end radius2: INTEGER -- The vertical radius. local l_point_array: like point_array p0, p1: EV_COORDINATE do l_point_array := point_array p0 := l_point_array.item (0) p1 := l_point_array.item (1) Result := as_integer ((p0.y_precise - p1.y_precise) / 2).abs end point_a_x: INTEGER -- x position of `point_b'. do Result := point_array.item (0).x end point_a_y: INTEGER -- y position of `point_b'. do Result := point_array.item (0).y end point_b_x: INTEGER -- x position of `point_b'. do Result := point_array.item (1).x end point_b_y: INTEGER -- y position of `point_b'. do Result := point_array.item (1).y end feature -- Element change set_radius1 (radius: INTEGER) -- Set `radius1' to `radius'. require radius_positive: radius >= 0 local l_point_array: like point_array p0, p1: EV_COORDINATE cx: DOUBLE do l_point_array := point_array p0 := l_point_array.item (0) p1 := l_point_array.item (1) cx := (p0.x_precise + p1.x_precise) / 2 p0.set_x_precise (cx - radius) p1.set_x_precise (cx + radius) invalidate center_invalidate ensure set: radius1 = radius end set_radius2 (radius: INTEGER) -- Set `radius2' to `radius'. require radius_positive: radius >= 0 local l_point_array: like point_array p0, p1: EV_COORDINATE cy: DOUBLE do l_point_array := point_array p0 := l_point_array.item (0) p1 := l_point_array.item (1) cy := (p0.y_precise + p1.y_precise) / 2 p0.set_y_precise (cy - radius) p1.set_y_precise (cy + radius) invalidate center_invalidate ensure set: radius2 = radius end set_radius1_and_radius2 (a_radius1, a_radius2: INTEGER) -- Set `radius1' to `a_radius1' and `radius2` to `a_radius2'. require radius1_positive: a_radius1 >= 0 radius2_positive: a_radius2 >= 0 local l_point_array: like point_array p0, p1: EV_COORDINATE cx, cy: DOUBLE do l_point_array := point_array p0 := l_point_array.item (0) p1 := l_point_array.item (1) cx := (p0.x_precise + p1.x_precise) / 2 cy := (p0.y_precise + p1.y_precise) / 2 p0.set_x_precise (cx - a_radius1) p1.set_x_precise (cx + a_radius1) p0.set_y_precise (cy - a_radius2) p1.set_y_precise (cy + a_radius2) invalidate center_invalidate ensure set: radius1 = a_radius1 and radius2 = a_radius2 end set_point_a_position (ax, ay: INTEGER) -- Set position of `point_a' to position of (`ax', `ay'). do point_array.item (0).set_precise (ax, ay) invalidate center_invalidate end set_point_b_position (ax, ay: INTEGER) -- Set position of `point_b' to position of (`ax', `ay'). do point_array.item (1).set_precise (ax, ay) invalidate center_invalidate end feature -- Events bounding_box: EV_RECTANGLE -- Smallest orthegonal rectangle `Current' fits in. local min_x, min_y, max_x, max_y, lw2, v1, v2: DOUBLE lx, ly, w, h: INTEGER l_point_array: like point_array pa, pb: EV_COORDINATE do if attached internal_bounding_box as l_internal_bounding_box and then l_internal_bounding_box.has_area then Result := l_internal_bounding_box.twin else l_point_array := point_array pa := l_point_array.item (0) pb := l_point_array.item (1) v1 := pa.x_precise v2 := pb.x_precise min_x := v1.min (v2) max_x := v1.max (v2) v1 := pa.y_precise v2 := pb.y_precise min_y := v1.min (v2) max_y := v1.max (v2) check max_x >= min_x max_y >= min_y end lw2 := line_width / 2 lx := as_integer (min_x - lw2) ly := as_integer (min_y - lw2) w := as_integer ((max_x - min_x) + lw2) + 1 h := as_integer ((max_y - min_y) + lw2) + 1 create Result.make (lx, ly, w, h) if attached internal_bounding_box as l_internal_bounding_box then l_internal_bounding_box.copy (Result) else internal_bounding_box := Result.twin end end end feature {NONE} -- Implementation set_center -- Set position of the center. local l_point_array: like point_array pa, pb: EV_COORDINATE do l_point_array := point_array pa := l_point_array.item (0) pb := l_point_array.item (1) center.set_precise ((pa.x_precise + pb.x_precise) / 2, (pa.y_precise + pb.y_precise) / 2) is_center_valid := True end note copyright: "Copyright (c) 1984-2006, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 356 Storke Road, Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class EV_MODEL_ELLIPTIC