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






