Click here to Skip to main content
15,891,905 members
Articles / Programming Languages / C#

Drawing Component to build GIS and CAM applications

Rate me:
Please Sign up or sign in to vote.
4.72/5 (14 votes)
21 Nov 20055 min read 107.9K   8K   123  
An object oriented drawing component for building GIS and CAM applications with multiple views of geometrical model, multiple resolution handling, layers, optimized graphics and more.
/**************************************************************** 
**  Copyright (C) 2004 MvisionTech Ltd.  
**  Copyright (C) 2005 Roadware Inc.
**
** This file is part of the Canvas.NET data visualization framework.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
**********************************************************************/

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Diagnostics;

namespace GeomModel 
{
	
	public class RotatedRectangle
	{
		public System.Drawing.Drawing2D.Matrix trans;
		public RectangleF rect;

		public ArrayList ConvertToPoly()
		{
			PointF [] points = { rect.Location, new PointF(rect.Right,rect.Top), 
								   new PointF(rect.Right,rect.Bottom),
								   new PointF(rect.Left,rect.Bottom) };
			trans.TransformPoints(points);			
			ArrayList poly_points = new ArrayList(points);
			PointF ps = (PointF)poly_points[0];
			poly_points.Add(new PointF(ps.X,ps.Y));
			return poly_points;
		}

		public RotatedRectangle(RectangleF r,System.Drawing.Drawing2D.Matrix t)
		{
			rect = r;
			trans = t.Clone();
		}

		public RotatedRectangle(RectangleF r,float sx,float sy, float angle)
		{
			rect = r;
			trans = new System.Drawing.Drawing2D.Matrix();			
			
			trans.Translate(sx,sy);
			trans.RotateAt(angle,new PointF(sx,sy),System.Drawing.Drawing2D.MatrixOrder.Append);
			
		}

		public ArrayList IntersectionLocal(RectangleF r1,
			System.Drawing.Drawing2D.Matrix t1)
		{
			System.Drawing.Drawing2D.Matrix t2 = t1.Clone();
			System.Drawing.Drawing2D.Matrix t_inv = trans.Clone();
				
			t_inv.Invert();
			t2.Multiply(t_inv,System.Drawing.Drawing2D.MatrixOrder.Append);				
				
			PointF [] points = { r1.Location, new PointF(r1.Right,r1.Top), 
								   new PointF(r1.Right,r1.Bottom),new PointF(r1.Left,r1.Bottom) };
			t2.TransformPoints(points);
			
			ArrayList poly_points = new ArrayList(points);
			ArrayList clip = Geom.ClipPolylineOnRectangle(rect,poly_points);
			
			return clip;
		}

		public ArrayList Intersection(RotatedRectangle r1)
		{
			return Intersection(r1.rect,r1.trans);
		}

		public bool IsIntersected(RotatedRectangle r1)
		{
			ArrayList clip = Intersection(r1);
			if(clip.Count == 0)
				return false;

			return true;
		}

		public ArrayList Intersection(RectangleF r1,
			System.Drawing.Drawing2D.Matrix t1)
		{
			ArrayList clip = IntersectionLocal(r1,t1);
			ArrayList clip_t = new ArrayList();
			foreach(ArrayList segment in clip)
			{
				PointF [] ps = new PointF [segment.Count];
				segment.CopyTo(ps);
				trans.TransformPoints(ps);	
				clip_t.Add(new ArrayList(ps));
			}

			return clip_t;
		}

		public bool IsIntersected(RectangleF r1,
			System.Drawing.Drawing2D.Matrix t1)
		{			
			ArrayList clip = IntersectionLocal(r1,t1);

			if(clip.Count == 0)
				return false;

			return true;
		}
	}

	public class ObjectsGrid
	{

		ArrayList m_objects_grid = new ArrayList();
		public float m_grid_x = 0;
		public float m_grid_y = 0;
		public float m_grid_w = 0;
		public float m_grid_h = 0;
		public float m_grid_dx = 0;
		public float m_grid_dy = 0;
		
		public int m_grid_cell_div = 20;
		

		public void Clear()
		{
			m_objects_grid.Clear();
		}

		public int Count
		{
			get 
			{
				return m_objects_grid.Count; 
			}			
		}

		public void draw(Graphics graphics, System.Drawing.Drawing2D.Matrix trans)
		{
			
			System.Drawing.Pen y_pen = new Pen(System.Drawing.Color.GreenYellow,1);
			System.Drawing.Pen g_pen = new Pen(System.Drawing.Color.Green,1);

			for(int k=0; k<m_grid_cell_div*m_grid_cell_div; k++)
			{
				int cnt = ((ArrayList)m_objects_grid[k]).Count;
				float y1 = m_grid_y+(k/m_grid_cell_div)*m_grid_dy;
				float x1 = m_grid_x+(k%m_grid_cell_div)*m_grid_dx;
				PointF [] cell_points = { new PointF(x1,y1), 
											new PointF(x1+m_grid_dx,y1+m_grid_dy)};
				
				trans.TransformPoints(cell_points);
				System.Drawing.Pen c_pen = y_pen;
				if(cnt > 0)
					c_pen = g_pen;

				graphics.DrawRectangle(c_pen,cell_points[0].X,
					cell_points[0].Y,
					cell_points[1].X-cell_points[0].X,
					cell_points[1].Y-cell_points[0].Y);


			}
		}

		/// <summary>
		/// Move object to the new location.
		/// </summary>
		/// <param name="old_box"></param>
		/// <param name="new_box"></param>
		/// <param name="shape_id"></param>
		/// <returns></returns>
		public bool moveObject(RectangleF old_box,RectangleF new_box,
								int shape_id)
		{
			if(m_grid_x > new_box.X ||
				m_grid_y > new_box.Y || 
				m_grid_x+m_grid_w < new_box.X+new_box.Width ||
				m_grid_y+m_grid_h < new_box.Y+new_box.Height )
			{
				this.Clear();
				return true;
			}

			// remove from old location:
			int grid_x1 = (int)((old_box.X-m_grid_x)/m_grid_dx);
			int grid_y1 = (int)((old_box.Y-m_grid_y)/m_grid_dy);

			int grid_x2 = (int)((old_box.X+old_box.Width-m_grid_x)/m_grid_dx);
			int grid_y2 = (int)((old_box.Y+old_box.Height-m_grid_y)/m_grid_dy);
		
			grid_x2 += 1;			
			grid_y2 += 1;

			if(grid_x1 < 0)
				grid_x1 = 0;
			if(grid_x2 > m_grid_cell_div)
				grid_x2 = m_grid_cell_div;
			
			if(grid_y1 < 0)
				grid_y1 = 0;
			if(grid_y2 > m_grid_cell_div)
				grid_y2 = m_grid_cell_div;
		
			for(int y1=grid_y1; y1<grid_y2; y1++)
				for(int x1=grid_x1; x1<grid_x2; x1++)
				{
					int it = y1*m_grid_cell_div+x1;
					if(it >= m_objects_grid.Count)
						continue;

					ArrayList obj_list = (ArrayList)m_objects_grid[it];					
					int indx = obj_list.IndexOf(shape_id);
					if(indx > 0)
						obj_list.RemoveAt(indx);
				}

			grid_x1 = (int)((new_box.X-m_grid_x)/m_grid_dx);
			grid_y1 = (int)((new_box.Y-m_grid_y)/m_grid_dy);

			grid_x2 = (int)((new_box.X+new_box.Width-m_grid_x)/m_grid_dx);
			grid_y2 = (int)((new_box.Y+new_box.Height-m_grid_y)/m_grid_dy);
		
			grid_x2 += 1;			
			grid_y2 += 1;  

			if(grid_x1 < 0)
				grid_x1 = 0;
			if(grid_x2 > m_grid_cell_div)
				grid_x2 = m_grid_cell_div;
			
			if(grid_y1 < 0)
				grid_y1 = 0;
			if(grid_y2 > m_grid_cell_div)
				grid_y2 = m_grid_cell_div;
		
			for(int y1=grid_y1; y1<grid_y2; y1++)
				for(int x1=grid_x1; x1<grid_x2; x1++)
				{
					int it = y1*m_grid_cell_div+x1;
					if(it>=m_objects_grid.Count)
						continue;
					ArrayList obj_list = (ArrayList)m_objects_grid[it];										
					if(obj_list.IndexOf(shape_id) < 0)
						obj_list.Add(shape_id);
				}

			return true;
		}

		public SortedList getObjects(RectangleF brect)
		{
			SortedList sorted_list = new SortedList();

			int grid_x1 = (int)((brect.X-m_grid_x)/m_grid_dx);
			int grid_y1 = (int)((brect.Y-m_grid_y)/m_grid_dy);
			int grid_x2 = (int)((brect.Right-m_grid_x)/m_grid_dx);
			int grid_y2 = (int)((brect.Bottom-m_grid_y)/m_grid_dy);
		
			grid_x2 += 1;			
			grid_y2 += 1;

			if(grid_x1 < 0)
				grid_x1 = 0;
			if(grid_x2 > m_grid_cell_div)
				grid_x2 = m_grid_cell_div;
			
			if(grid_y1 < 0)
				grid_y1 = 0;
			if(grid_y2 > m_grid_cell_div)
				grid_y2 = m_grid_cell_div;
		
			for(int y1=grid_y1; y1<grid_y2; y1++)
				for(int x1=grid_x1; x1<grid_x2; x1++)
				{
					ArrayList obj_list = (ArrayList)m_objects_grid[y1*m_grid_cell_div+x1];					
					foreach(int item in obj_list)
					{
						if(!sorted_list.Contains(item))
							sorted_list.Add(item,item);						
					}	
				}

			return sorted_list;
		}

		public RectangleF BoundingBox()
		{
			return new RectangleF(m_grid_x,m_grid_y,
					m_grid_w,m_grid_h);
		}

		public bool create(SortedList canvas_objects,CanvasLayer lay)
		{
			m_objects_grid.Clear();
			
			int obj_count = 0;
			foreach(int indx in canvas_objects.Keys)
			{					
				CanvasItem item = (CanvasItem)(canvas_objects[indx]);
				
				if(item.layer == lay)
					obj_count++;
			}

			if(obj_count > 100)
				m_grid_cell_div = 100;
			else
				m_grid_cell_div = obj_count;
			

			if(canvas_objects.Count == 0)
				return false;
	
			for(int k=0; k<m_grid_cell_div*(m_grid_cell_div+1)+1; k++)
			{
				m_objects_grid.Insert(k,new ArrayList());
			}

			//RectangleF bbox = calcBoundingBox();
			
			
			//m_grid_x = ((CanvasItem)canvas_objects[0]).X();
			//m_grid_y = ((CanvasItem)canvas_objects[0]).Y();
			m_grid_x = m_grid_w = 0;
			m_grid_y = m_grid_h = 0;

			float max_x = m_grid_x;
			float max_y = m_grid_y;
			bool first_item = true;
			// get items bounded box:
			foreach(int indx in canvas_objects.Keys)
			{					
				CanvasItem item = (CanvasItem)(canvas_objects[indx]);
				
				if(item.layer != lay)
					continue;

				RectangleF item_bbox = item.boundingBox();
				if(first_item)
				{
					m_grid_x = item_bbox.Left;
					m_grid_y = item_bbox.Top;
					max_x = item_bbox.Right;
					max_y = item_bbox.Bottom;
					first_item = false;
					continue;	
				}
				
				if(m_grid_x > item_bbox.Left)
					m_grid_x = item_bbox.Left;
				else if(max_x < item_bbox.Right)
					max_x = item_bbox.Right;

				if(m_grid_y > item_bbox.Top)
					m_grid_y = item_bbox.Top;
				else if(max_y < item_bbox.Bottom)
					max_y = item_bbox.Bottom;
			}
			
			m_grid_w = max_x - m_grid_x;
			m_grid_h = max_y - m_grid_y;

			if(m_grid_w == 0)
				m_grid_w = 1;
			
			if(m_grid_h == 0)
				m_grid_h = 1;

			m_grid_dx = m_grid_w/m_grid_cell_div;
			m_grid_dy = m_grid_h/m_grid_cell_div;
						
			foreach(int indx in canvas_objects.Keys)
			{					
				CanvasItem item = (CanvasItem)(canvas_objects[indx]);
				if(item.layer != lay)
					continue;

				RectangleF item_bbox = item.boundingBox();
				int x_indx_1 = (int)((item_bbox.X-m_grid_x)/m_grid_dx);
				int y_indx_1 = (int)((item_bbox.Y-m_grid_y)/m_grid_dy);
				int x_indx_2 = (int)((item_bbox.X+item_bbox.Width-m_grid_x)/m_grid_dx);
				int y_indx_2 = (int)((item_bbox.Y+item_bbox.Height-m_grid_y)/m_grid_dy);
				
				for(int y_c=y_indx_1; y_c<=y_indx_2; y_c++)
					for(int x_c=x_indx_1; x_c<=x_indx_2; x_c++)
					{
						int grid_indx = y_c*m_grid_cell_div+x_c;
						if(grid_indx >= m_objects_grid.Count || grid_indx<0)
							continue;

						ArrayList obj_list = (ArrayList)m_objects_grid[grid_indx];
						obj_list.Add(indx);						
					}
			}

			return true;
		}		
	}

	public class CanvasLayer
	{
		SortedList m_string_list = new SortedList();
		SortedList m_id_to_string_map = new SortedList();
		int curr_string_id;
		Color m_label_color = Color.Black;
		Color m_label_color_bg = Color.WhiteSmoke;
		bool m_fill_label_bg = true;

		public Color LabelColorBg
		{
			get
			{
				return m_label_color_bg;
			}

			set 
			{
				m_label_color_bg = value;
			}
		}

		public Color LabelColor
		{
			get
			{
				return m_label_color;
			}

			set 
			{
				m_label_color = value;
			}
		}

		public bool FillLabelBg
		{
			get
			{
				return m_fill_label_bg;
			}

			set
			{
				m_fill_label_bg = value;
			}
		}

		public string ShapeGetLabel(int shape_id)
		{
			if(!m_id_to_string_map.ContainsKey(shape_id))
				return "none";

			return (string)m_string_list[(int)m_id_to_string_map[shape_id]];
		}

		public bool ShapeHasLabel(int shape_id)
		{			
			return m_id_to_string_map.ContainsKey(shape_id);
		}

		public bool ShapeDeleteLabel(int shape_id)
		{
			if(!m_id_to_string_map.ContainsKey(shape_id))
				return false;

			int sh_key = (int)m_id_to_string_map[shape_id];
			m_string_list.RemoveAt(m_string_list.IndexOfKey(sh_key));
			return true;
		}

		public bool ShapeAddLabel(int shape_id,string label)
		{
			int str_indx = m_string_list.IndexOfValue(label);
			int string_id = curr_string_id;
			if(str_indx >= 0)
			{
				string_id = (int)m_string_list.GetKey(str_indx);	
			}
			else
			{
				string_id = curr_string_id++;
				m_string_list.Add(string_id,label);
			}

			if(m_id_to_string_map.ContainsKey(shape_id))
			{
				m_id_to_string_map[shape_id] = string_id;
			}
			else
			{
				m_id_to_string_map.Add(shape_id,string_id);
			}
			
			return true;
		}

		public Color FillColor 
		{
			get
			{
				return bg_color;
			}

			set 
			{
				bg_color = value;
			}
		}

		public  bool Fill
		{
			get
			{
				return m_fill;
			}

			set
			{
				m_fill = value;
			}
		}

		public Color Color
		{
			get
			{
				return color;
			}
			set
			{
				color = value;
			}
		}
		
		bool m_fill = false;
		Color color = Color.Purple;
		Color bg_color = Color.GreenYellow;
		ObjectsGrid m_objects_grid;
		double m_max_scale = -1;

		public ObjectsGrid Grid
		{
			get
			{
				return m_objects_grid;
			}
		}

		public double MinScale
		{
			get 
			{
				return visiableOnScale;
			}
			set 
			{
				visiableOnScale = value;
			}
		}

		public double MaxScale
		{
			get 
			{
				return m_max_scale;
			}
			set 
			{
				m_max_scale = value;
			}
		}

		double visiableOnScale = 0;
	
		public int Order = 0;

		public float LineWidth
		{
			get 
			{
				return (float)line_width;
			}
			set
			{
				line_width = value;
			}
		}

		double line_width = 2;

		public bool Visiable
		{
			get 
			{
				return visiable;
			}
			set 
			{
				visiable = value;
			}
		}

		bool visiable = true;
		private ArrayList itemsList;
		public string Name
		{
			get 
			{
				return name;
			}
			set
			{
				name = value;
			}
		}

		string name;
		
	

		public CanvasLayer(string n,Color col,int z,bool v)
		{
			name = n;
			color = col;
			visiableOnScale = z;
			visiable = v;
			itemsList = new ArrayList();
			m_objects_grid = new ObjectsGrid();
		}

		public void add(CanvasItem i)
		{
			itemsList.Add(i);
		}

		public ArrayList getItems()
		{
			return itemsList;
		}
	}

	/// <summary>
	/// 2D geometry functions used in Canvas.
	/// </summary>
	public class Geom 
	{
		public static ArrayList ClipSegmentOnRectangle(PointF p0,PointF p1,RectangleF r)
		{
			ArrayList al = new ArrayList();
			PointF p_1 = new PointF();
			PointF p_2 = new PointF();
			try
			{
				if(!Geometry.Clip.SegmentOnRectangle(ref p0,ref p1,ref r,ref p_1,ref p_2))
					return new ArrayList();
				al.Add(p_1);
				al.Add(p_2);
			}
			catch
			{
				return new ArrayList();
			}

			/*
			// check left facet:
			ArrayList al = new ArrayList();
			float dx = p0.X	- p1.X;
			float dy = p0.Y	- p1.Y;

			if(dx==0 && dy==0)
				return new ArrayList();

			float left = (p0.X < p1.X) ? p0.X : p1.X;
			bool left_intersect = false;
			if((p0.X < r.Left && p1.X > r.Left) || (p0.X > r.Left && p1.X < r.Left))	
			{
				left_intersect = true;
				left = r.Left;
				
			}
			// check top facet:
			bool top_intersect = false;
			float top = (p0.Y < p1.Y) ? p0.Y : p1.Y;
			if((p0.Y < r.Top && p1.Y > r.Top) || (p0.Y > r.Top && p1.Y < r.Top))	
			{
				top_intersect = true;
				top = r.Top;
			}
			// check right facet:
			bool right_intersect = false;
			float right = (p0.X < p1.X) ? p0.X : p1.X;
			if((p0.X < r.Right && p1.X > r.Right) || (p0.X > r.Right && p1.X < r.Right))	
			{
				right_intersect = true;
				right = r.Right;
			}
			// check bottom
			bool bottom_intersect = false;
			float bottom = (p0.Y < p1.Y) ? p0.Y : p1.Y;
			if((p0.Y < r.Bottom && p1.Y > r.Bottom) || (p0.Y > r.Bottom && p1.X < r.Bottom))	
			{
				bottom_intersect = true;
				bottom = r.Bottom;
			}

			// check intersection states:
			if(left_intersect)
			{
				al.Add(new PointF(left,(left-p0.X)*dy/dx));
				if(top_intersect)
				{					 					
					al.Add(new PointF((top-p0.Y)*dx/dy,top));
					return al;
				}
				else if(bottom_intersect)
				{					
					al.Add(new PointF((p0.Y-bottom)*dx/dy,bottom));
					return al;
				}
				else if(right_intersect)
				{					
					al.Add(new PointF(right,(p0.Y-right)*dx/dy));
					return al;
				}
				else
				{
					if(r.Contains(p0))
						al.Add(p0);
					else if(r.Contains(p1))
						al.Add(p1);
					else
						al.Clear();
					return al;
				}
			}
			else if(top_intersect)
			{
				al.Add(new PointF((p0.Y-top)*dx/dy,top));
				if(bottom_intersect)
				{					
					al.Add(new PointF((p0.Y-bottom)*dx/dy,bottom));
					return al;
				}
				else if(right_intersect)
				{					
					al.Add(new PointF(right,(p0.Y-right)*dx/dy));
					return al;
				}
				else
				{
					if(r.Contains(p0))
						al.Add(p0);
					else if(r.Contains(p1))
						al.Add(p1);
					else
						al.Clear();
					return al;
				}
			}
			else if(right_intersect)
			{
				al.Add(new PointF(right,(p0.Y-right)*dx/dy));
				if(bottom_intersect)
				{					
					al.Add(new PointF((p0.Y-bottom)*dx/dy,bottom));
					return al;
				}
				else
				{
					if(r.Contains(p0))
						al.Add(p0);
					else if(r.Contains(p1))
						al.Add(p1);
					else
						al.Clear();
					return al;
				}
			}

			if(r.Contains(p0))
				al.Add(p0);
			else if(r.Contains(p1))
				al.Add(p1);
			else
				al.Clear();
				*/
			return al;			
		}

		public static ArrayList ClipPolylineOnRectangle(RectangleF r,ArrayList m_points)
		{
			// return empty array if there are no points:
			if(m_points.Count == 0)
				return new ArrayList();

			ArrayList segments = new ArrayList();
			bool prev_out = false;
			PointF prev_point = (PointF)m_points[0]; 
			ArrayList al = new ArrayList();
			for(int i=0; i<m_points.Count; i++)
			{
				PointF p = (PointF)m_points[i];				
				if(prev_out || !r.Contains(p) && i > 0 )
				{					
					ArrayList cliped_line = ClipSegmentOnRectangle(prev_point,p,r);
					if(cliped_line.Count > 0)
						al.AddRange(cliped_line);

				}				
				
				if(r.Contains(p))
				{
					if(!prev_out)
						al.Add(p);					

					prev_out = false;
				}
				else
				{
					if(al.Count > 0)
					{
						segments.Add(al);
						al = new ArrayList();
					}
					prev_out = true;
				}
				prev_point = p;
			}
			// save last segment:
			if(al.Count > 0)
			{
				segments.Add(al);
			}

			return segments;
		}


		public static RectangleF BoundingBox(ArrayList points)
		{
			RectangleF brect = new RectangleF(0,0,0,0);

			if(points.Count == 0)
				return brect;

			float min_x = ((PointF)points[0]).X;
			float min_y = ((PointF)points[0]).Y;
			float max_x = min_x;
			float max_y = min_y;

			foreach(PointF p in points)
			{
				if(p.X < min_x)
					min_x = p.X;
				else if(p.X > max_x)
					max_x = p.X;

				if(p.Y < min_y)
					min_y = p.Y;
				else if(p.Y > max_y)
					max_y = p.Y;
			}
			
			brect.X = min_x;
			brect.Y = min_y;
			brect.Width = max_x - min_x;
			brect.Height = max_y - min_y;

			return brect;
		}

		public static RectangleF BoundingBox(PointF [] points)
		{
			RectangleF brect = new RectangleF(0,0,0,0);

			if(points.Length == 0)
				return brect;

			float min_x = ((PointF)points[0]).X;
			float min_y = ((PointF)points[0]).Y;
			float max_x = min_x;
			float max_y = min_y;

			foreach(PointF p in points)
			{
				if(p.X < min_x)
					min_x = p.X;
				else if(p.X > max_x)
					max_x = p.X;

				if(p.Y < min_y)
					min_y = p.Y;
				else if(p.Y > max_y)
					max_y = p.Y;
			}
			
			brect.X = min_x;
			brect.Y = min_y;
			brect.Width = max_x - min_x;
			brect.Height = max_y - min_y;

			return brect;
		}

		public static bool pointInRect(PointF p,RectangleF rect)
		{
			return (p.X > rect.X) && (p.X < rect.X + rect.Width)
				&& (p.Y > rect.Y) && (p.Y < rect.Y + rect.Height);
		}

		/// <summary>
		/// calculate area of triangle defined by 3 points
		/// </summary>
		public static double triArea2(PointF p0,PointF p1,PointF p2)
		{
			return (p0.Y - p2.Y) * (p1.X - p2.X) - (p1.Y - p2.Y) * (p0.X - p2.X);
		}

		/// <summary>
		/// calculate square distance between 2 poins
		/// </summary>
		public static double sqrDistance(PointF p1,PointF p2)
		{
			double dx = p1.X-p2.X;
			double dy = p1.Y-p2.Y;

			return dx*dx+dy*dy;
		}

		/// <summary>
		/// calculate square distance from point p to segment [s0,s1]
		/// </summary>
		public static double segmentToPointSqrDist(PointF s0, PointF s1,PointF p)
		{
			double s1p_sqr  = sqrDistance(s1, p );
			double ps0_sqr  = sqrDistance(p , s0);
			double s0s1_sqr = sqrDistance(s0, s1);

			if (s1p_sqr < s0s1_sqr) 
			{
				if(s0s1_sqr < ps0_sqr) 
				{

					// ps0_sqr s0s1_sqr s1p_sqr
					if (s0s1_sqr + s1p_sqr <= ps0_sqr)
						return s1p_sqr;
				}

				// s0s1_sqr (s1p_sqr, ps0_sqr)
				if (s0s1_sqr <= s1p_sqr + ps0_sqr)
					return Math.Min(s1p_sqr, ps0_sqr);

			} 
			else 
			{
	
				// s1p_sqr s0s1_sqr
				if (s1p_sqr < ps0_sqr) 
				{

					// ps0_sqr s1p_sqr s0s1_sqr
					if (s1p_sqr + s0s1_sqr <= ps0_sqr)
						return s1p_sqr;

				} 
				else 
				{
					// s1p_sqr (s0s1_sqr, ps0_sqr)
					if (s0s1_sqr + ps0_sqr <= s1p_sqr)
						return ps0_sqr;
				}
			}
  
			double tri_area = triArea2(s0, s1, p);
			return tri_area*tri_area/s0s1_sqr;
		}
	}

	/// <summary>
	/// Canvas item base class specifies canvas item common behavior
	/// </summary>
	public abstract class CanvasItem 
	{
		//private Color color = Color.Purple;
		public CanvasLayer layer = null;

		public virtual ArrayList getBoundedPoints(RectangleF r)
		{
			ArrayList al = new ArrayList();
			ArrayList segment = new ArrayList();
			PointF p = new PointF(this.X(),this.Y());
			if(r.Contains(p))
			{
				segment.Add(p);
			}
			al.Add(segment);
			return al;
		}

		public virtual void rotate(double angle)
		{
		}

		public virtual void resize(RectangleF r)
		{
			
		}

		public virtual bool createFromLine(PointF p1,PointF p2)
		{
			return true;
		}

		public virtual bool createFromPolyline(ArrayList pl)
		{
			return true;
		}

		public virtual bool createFromRectangle(RectangleF r)
		{
			return true;
		}
		
		/// <summary>
		/// calculate shape bounding box.
		/// </summary>
		/// <returns> bounding box rectangle </returns>
		public abstract RectangleF boundingBox();
		/// <summary>
		/// get start point X
		/// </summary>
		/// <returns> X </returns>
		public abstract float X();
		/// <summary>
		/// get start point Y
		/// </summary>
		/// <returns> Y </returns>
		public abstract float Y();
		/// <summary>
		/// move shape to the point p.
		/// </summary>
		/// <param name="p"> destination point </param>
		public abstract void move(PointF p);
		/// <summary>
		/// move shape by delta X,Y
		/// </summary>
		/// <param name="x"> X shift </param>
		/// <param name="y"> Y shift </param>
		public abstract void moveBy(float x,float y);
		/// <summary>
		/// draw shape on graphic device.
		/// Shape stored in "real world" coordinates, converted 
		/// to client (graphic window) coordinate system and drawn 
		/// on graphic device
		/// </summary>
		/// <param name="graph"> graphic device </param>
		/// <param name="trans"> real to client transformation </param>
		public abstract void draw(Graphics graph,System.Drawing.Drawing2D.Matrix trans);
		/// <summary>
		/// Returns true if point close to the shape by specified distance 
		/// </summary>
		/// <param name="pnt"> source point </param>
		/// <param name="dist"> distance between shape and point </param>
		/// <returns></returns>
		public abstract bool isCloseToPoint(PointF pnt,float dist);
		/// <summary>
		/// Returns true if the shape is selected
		/// </summary>
		/// <returns> true or false </returns>
		public abstract bool isSelected();
		/// <summary>
		/// Select the shape if parameter is true. Deselect otherwice.
		/// </summary>
		/// <param name="m"> selection flag </param>
		public abstract void select(bool m);
	}



	public class ModelChangedEventArgs : EventArgs
	{
		public RectangleF rect;

		public ModelChangedEventArgs(RectangleF r)
		{
			rect = r;
		}
	}

	public class LayerEventArgs : EventArgs 
	{
		public CanvasLayer lay;

		public LayerEventArgs(CanvasLayer l)
		{
			lay = l;
		}
	}

	public class MesureEventArgs : EventArgs
	{
		public PointF p1;
		public PointF p2;

		public MesureEventArgs(PointF p_1,PointF p_2)
		{
			p1 = p_1;
			p2 = p_2;
		}
	}

	public class ItemEventArgs : EventArgs 
	{
		public int indx;

		public ItemEventArgs(int i)
		{
			indx = i;
		}
	}

	public class CoordEventArgs : EventArgs 
	{
		public float X;
		public float Y;
		public int R;
		public int G;
		public int B;

		public CoordEventArgs(float x,float y,int r,int g,int b)
		{
			X=x;
			Y=y;
			R=r;
			G=g;
			B=b;
		}
	}

	public class ViewEventArgs : EventArgs 
	{
		
		public object m_view;
		public RectangleF m_rect;

		public ViewEventArgs(object v,RectangleF r)
		{
			m_view = v;	
			m_rect = r;
		}
	}

	public class CanvasGeomModel 
	{
		private SortedList m_canvas_objects = new SortedList();
		private int m_curr_item_id = 0;
		private Image picture = null;
		//private ArrayList m_objects_grid;
		//private ObjectsGrid m_objects_grid;
	
		public ArrayList Objects
		{
			get
			{
				return new ArrayList(m_canvas_objects.Keys);
			}
		}
	
		public delegate void ItemChangedEventHandler(object sender, ItemEventArgs e);
		public delegate void ModelChangedEventHandler(object sender, ModelChangedEventArgs e);
	
		public event ItemChangedEventHandler ItemChangedEvent;
		public event ModelChangedEventHandler ModelChangedEvent;

		public delegate void ViewChangeEventHandler(object sender, ViewEventArgs e);
		public event ViewChangeEventHandler ViewChangeEvent;
		public delegate void LayerChangedEventHandler(object sender,LayerEventArgs e);
		public event LayerChangedEventHandler LayerChangedEvent;

		bool m_show_grid = false;

		ArrayList m_layers;
		bool m_debug = false;
		
		public bool Debug
		{
			get
			{
				return m_debug;
			}

			set
			{
				m_debug = value;
			}
		}

		//System.Diagnostics.PerformanceCounter cdCounter1;
		//System.Diagnostics.PerformanceCounter cdCounter2;

		private Color m_bgColor = Color.Gray;

		public Color BgColor 
		{
			set 
			{
				m_bgColor = value;
			}

			get
			{
				return m_bgColor;
			}
		}

		public void viewChanged(object view,RectangleF rect)
		{			
			if(ViewChangeEvent != null)
				ViewChangeEvent(this,new ViewEventArgs(view,rect));							
		}

		public CanvasLayer layerByName(string name)
		{
			foreach (CanvasLayer item in m_layers)
			{
				if( item.Name == name)
					return item;
			}

			return null;
		}
	
		public bool moveLayerUp(string lname)
		{
			SortedList sl = new SortedList();
			int s_order = -1;
			foreach(CanvasLayer lay in m_layers)
			{
				sl.Add(lay.Order,lay);
				if(lname == lay.Name)
				{
					s_order = lay.Order;
				}
			}

			if(s_order == -1)
				return false;

			int indx = sl.IndexOfKey(s_order);
			if(indx<sl.Count-1)
			{
				CanvasLayer pl = (CanvasLayer)sl.GetByIndex(indx);
				CanvasLayer nl = (CanvasLayer)sl.GetByIndex(indx+1);
				pl.Order = nl.Order;
				nl.Order = s_order;
				if(LayerChangedEvent != null)
					LayerChangedEvent(this,new LayerEventArgs(nl));
			}

			return true;
		}

		public bool moveLayerDown(string lname)
		{
			SortedList sl = new SortedList();
			int s_order = -1;
			foreach(CanvasLayer lay in m_layers)
			{
				sl.Add(lay.Order,lay);
				if(lname == lay.Name)
				{
					s_order = lay.Order;
				}
			}

			if(s_order == -1)
				return false;

			int indx = sl.IndexOfKey(s_order);
			if(indx>0)
			{
				CanvasLayer pl = (CanvasLayer)sl.GetByIndex(indx-1);
				CanvasLayer nl = (CanvasLayer)sl.GetByIndex(indx);
				nl.Order = pl.Order;
				pl.Order = s_order;
				if(LayerChangedEvent != null)
					LayerChangedEvent(this,new LayerEventArgs(pl));
			}
			return true;
		}

		public CanvasLayer createLayer(string name,Color color,int zoom,bool vis)
		{
			if( layerByName(name) != null)
				return null;
		
			CanvasLayer lay = new CanvasLayer(name,color,zoom,vis);
			lay.Order = m_layers.Count;
			m_layers.Add(lay);
			if(LayerChangedEvent != null)
				LayerChangedEvent(this,new LayerEventArgs(lay));

			return lay;
		}

		public void showGrid(bool m)
		{
			m_show_grid = m;			
		}

		public ArrayList getLayers()
		{
			return m_layers;
		}

		public CanvasGeomModel()
		{
			//m_objects_grid = new ArrayList();
			//m_objects_grid = new ObjectsGrid();

			m_layers = new ArrayList();		
		}

		public int Add(CanvasItem item)
		{
			m_canvas_objects.Add(m_curr_item_id,item);
			
			CanvasLayer lay = layerByName(item.layer.Name);
			// add new layer
			if( lay == null)
			{
				item.layer.Order = m_layers.Count;
				m_layers.Add(item.layer);
				

				if(LayerChangedEvent != null)
					LayerChangedEvent(this,new LayerEventArgs(item.layer));
			}

			item.layer.Grid.Clear();
			
			//m_objects_grid.Clear();

			if(ItemChangedEvent != null)
				ItemChangedEvent(this,new ItemEventArgs(m_curr_item_id));

			return m_curr_item_id++;
		}


		public bool getIntersected(ArrayList list)
		{
			
			return true;
		}
				
		public RectangleF BoundingBox()
		{
			ArrayList points = new ArrayList();
			foreach(CanvasLayer lay in m_layers)
			{
				RectangleF r = BoundingBox(lay);
				points.Add(new PointF(r.Left,r.Top));
				points.Add(new PointF(r.Right,r.Bottom));				
			}

			return Geom.BoundingBox(points);
		}

		public RectangleF BoundingBox(CanvasLayer lay)
		{
			if(!m_layers.Contains(lay))
				return new RectangleF(0,0,0,0);

			if(lay.Grid.Count == 0 && m_canvas_objects.Count != 0 )
				lay.Grid.create(m_canvas_objects,lay);
			
			return new RectangleF(lay.Grid.m_grid_x,
				lay.Grid.m_grid_y,
				lay.Grid.m_grid_w,
				lay.Grid.m_grid_h);
		}

		public CanvasItem GetItem(int indx)
		{
			return (CanvasItem)m_canvas_objects[indx];
		}

		public int [] GetSelected()
		{
			ArrayList selected_list = new ArrayList();
			for(int indx=0; indx < m_canvas_objects.Count; indx++)
			{					
				CanvasItem item = (CanvasItem)(m_canvas_objects.GetByIndex(indx));
				if(item.isSelected())
				{
					selected_list.Add(indx);
				}
			}

			int [] selection = new int[selected_list.Count];
			selected_list.CopyTo(0,selection,0,selection.Length);
			return selection;
		}

		public void MoveItem(int shape_id,PointF p)
		{
			if(!m_canvas_objects.ContainsKey(shape_id))
			{
				return;
			}

			CanvasItem ci = (CanvasItem)m_canvas_objects[shape_id];			
			ArrayList points = new ArrayList();

			RectangleF r1 = ci.boundingBox();

			points.Add(new PointF(r1.Left,r1.Top));
			points.Add(new PointF(r1.Right,r1.Bottom));

			points.Add(new PointF(p.X,p.Y));
			points.Add(new PointF(p.X+r1.Width,p.Y+r1.Height));

			// move an object in the objects grid:
			RectangleF r2 = new RectangleF(p,r1.Size);
			ci.layer.Grid.moveObject(r1,r2,shape_id);

			ci.move(p);
			RectangleF bbox = Geom.BoundingBox(points);

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(bbox));
		}
		
		public void DeleteItem(int shape_id)
		{
			if(!m_canvas_objects.ContainsKey(shape_id))
			{
				return;
			}

			//m_objects_grid.Clear();
			CanvasItem canv_item = (CanvasItem)m_canvas_objects[shape_id];
			if(canv_item == null)
				return;

			canv_item.layer.Grid.Clear();

			RectangleF bbox = canv_item.boundingBox();

			CanvasLayer lay = canv_item.layer;
			if(lay.getItems().Contains(canv_item))
				lay.getItems().Remove(canv_item);

			m_canvas_objects.RemoveAt(m_canvas_objects.IndexOfKey(shape_id));
			
			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(bbox));
		}

		public void DeleteSelected()
		{
			//m_objects_grid.Clear();

			bool not_passed = true;

			ArrayList points = new ArrayList();

			while(not_passed)
			{
				not_passed = false;
				for(int indx=0; indx < m_canvas_objects.Count; indx++)
				{					
					CanvasItem item = (CanvasItem)(m_canvas_objects.GetByIndex(indx));
					
					if(item.isSelected())
					{
						RectangleF r1 = item.boundingBox();

						points.Add(new PointF(r1.Left,r1.Top));
						points.Add(new PointF(r1.Right,r1.Bottom));

						m_canvas_objects.RemoveAt(indx);
						item.layer.Grid.Clear();

						not_passed = true;
						break;
					}
				}
			}
			
			RectangleF bbox = Geom.BoundingBox(points);

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(bbox));
		}

		public void moveBySelected(float dx,float dy)
		{
			// move selected objects

			ArrayList points = new ArrayList();

			for(int indx=0; indx < m_canvas_objects.Count; indx++)
			{
				CanvasItem item = (CanvasItem)(m_canvas_objects.GetByIndex(indx));
				if(item.isSelected())
				{
					RectangleF r1 = item.boundingBox();

					points.Add(new PointF(r1.Left,r1.Top));
					points.Add(new PointF(r1.Right,r1.Bottom));

					points.Add(new PointF(r1.Left+dx,r1.Top+dy));
					points.Add(new PointF(r1.Right+dx,r1.Bottom+dy));

					RectangleF r2 = new RectangleF(r1.Left+dx,r1.Top+dy,
						r1.Width,r1.Height);

					item.layer.Grid.moveObject(r1,r2,indx);
					
					item.moveBy(dx,dy);
					if(ModelChangedEvent != null)
						ModelChangedEvent(this,new ModelChangedEventArgs(item.boundingBox()));
	
				}
			}

			RectangleF bbox = Geom.BoundingBox(points);

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(bbox));
		}

		public CanvasItem GetByIndex(int indx)
		{
			return (CanvasItem)(m_canvas_objects.GetByIndex(indx));
		}

		public int Count 
		{
			get 
			{
				return m_canvas_objects.Count;
			}
		}

		public int GetKey(int indx)
		{
			return (int)m_canvas_objects.GetKey(indx);
		}
		
		public CanvasItem GetByKey(int key)
		{
			return (CanvasItem)m_canvas_objects[key];
		}
	
	
	
		public void draw(Graphics graphics,System.Drawing.Drawing2D.Matrix trans,bool draw_labels)
		{
			RectangleF rect = graphics.ClipBounds;
			rect.X = rect.X-5;
			rect.Y =rect.Y-5;
			
			rect.Width+=10;
			rect.Height+=10;
			
			if(rect.Width == 0 || rect.Height == 0)
				return;

			string d_msg = "draw rect "+rect.Size.ToString();
			Trace.WriteLine(d_msg);
			long start_draw_t = DateTime.Now.Ticks;
						
			Bitmap bmp = new Bitmap((int)rect.Width,(int)rect.Height);
			Graphics temp_graph = Graphics.FromImage(bmp);
			//SolidBrush brush = new SolidBrush(Color.Gray);
			SolidBrush brush = new SolidBrush(m_bgColor);

			temp_graph.FillRectangle(brush,0,0,rect.Width,rect.Height);
		
			System.Drawing.Drawing2D.Matrix inv_trans = trans.Clone();
			inv_trans.Invert();
		
			PointF [] src_pnts = {new PointF(rect.X,rect.Y),
									 new PointF(rect.X+rect.Width,rect.Y+rect.Height)};
			
			inv_trans.TransformPoints(src_pnts);
			RectangleF bmp_rect = new RectangleF(0,0,rect.Width,rect.Height);
			/*
			RectangleF src_rect = new RectangleF(src_pnts[0].X,
				src_pnts[0].Y,
				src_pnts[1].X-src_pnts[0].X,
				src_pnts[1].Y-src_pnts[0].Y);
*/
			RectangleF src_rect = Geom.BoundingBox(src_pnts);
			
			//RectangleF rect = new RectangleF(0,0,this.Width+1,this.Height+1);
			//graphics.Transform = m_trans;
			if(this.picture != null)
			{							
				temp_graph.DrawImage(this.picture, bmp_rect,src_rect,GraphicsUnit.Pixel);								
			}
			
			
			graphics.DrawImage(bmp,rect);
			bmp.Dispose();
			temp_graph.Dispose();
			brush.Dispose();

			SortedList lay_list = new SortedList();
			// sort layers list 
			foreach(CanvasLayer lay in m_layers)
			{
				lay_list.Add(lay.Order,lay);
			}
			
			
			foreach(int key in lay_list.Keys)
			{
				SortedList labels_list = new SortedList();

				CanvasLayer curr_lay = (CanvasLayer)lay_list[key];
				if(!curr_lay.Visiable)
					continue;

				float scale = Math.Abs(trans.Elements[0]);
				if(scale < curr_lay.MinScale)
					continue;

				if(curr_lay.MaxScale > 0 && scale > curr_lay.MaxScale)
					continue;

				if(curr_lay.Grid.Count == 0)
					curr_lay.Grid.create(m_canvas_objects,curr_lay);
		
				if(m_show_grid)
				{					
					curr_lay.Grid.draw(graphics,trans);			
				}
				
				// display objects in overlapped by the view grid cells				
				SortedList sorted_list = curr_lay.Grid.getObjects(src_rect);
			
				string msg = "display " + sorted_list.Count.ToString() + " objects";
				Trace.Indent();
				Trace.WriteLine(msg);

				long start_t = DateTime.Now.Ticks;
				//Console.WriteLine( "\t-KEY-\t-VALUE-" );
			
				RectangleF client_rect = new RectangleF();
				int n=0;
				foreach(int k in sorted_list.Keys)
				{
					if(!m_canvas_objects.ContainsKey(k))
						continue;
					
					int shape_id = k;
					CanvasItem item = (CanvasItem)(m_canvas_objects[shape_id]);
					if(item == null)
						continue;

					if(draw_labels && curr_lay.ShapeHasLabel(shape_id))
					{	
						ArrayList segments = item.getBoundedPoints(Geom.BoundingBox(src_pnts));
						if(segments.Count>0)
							labels_list.Add(shape_id,segments);
				
					}				
					item.draw(graphics,trans);
					
					if(n++>5000)
						break;
				}

				long end_t = DateTime.Now.Ticks;
				double diff = (end_t - start_t)/10000000.0;
				Trace.Indent();
				msg = "time=" + diff.ToString() + " sec";
				Trace.WriteLine(msg);
				Trace.Unindent();
				Trace.Unindent();
				diff = (end_t - start_draw_t)/10000000.0;
				msg = "total time = " + diff.ToString() + " sec";
				Trace.WriteLine(msg);

				DrawLabels(labels_list,curr_lay,graphics,trans);
			}

			
		}

		private bool DrawLabels(SortedList labels_list,CanvasLayer lay,Graphics graphics,System.Drawing.Drawing2D.Matrix trans)
		{
			// draw labels:
			long label_start_t = DateTime.Now.Ticks;
			System.Drawing.Font drawFont = new System.Drawing.Font("Arial", 6);
			System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(lay.LabelColor);
		
			System.Drawing.SolidBrush fillBrush = new System.Drawing.SolidBrush(lay.LabelColorBg);
	
			System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
			System.Drawing.Pen pen = new Pen(Color.Blue);

			ArrayList displayed_labels = new ArrayList();
			foreach(int shape_id in labels_list.Keys)
			{
				CanvasItem item = (CanvasItem)(m_canvas_objects[shape_id]);
				string label = item.layer.ShapeGetLabel(shape_id);
				PointF [] src_pnts1 = {new PointF(item.X(),item.Y())};
				trans.TransformPoints(src_pnts1);	
				float px = src_pnts1[0].X;
				float py = src_pnts1[0].Y;
				float angle = 0;
				
				RectangleF lrect = new RectangleF(0,0,drawFont.Size*label.Length,
					drawFont.Height);

				ArrayList al = (ArrayList)labels_list[shape_id];
				// get angle of the text from consequtive points:
				if(al.Count > 0)
				{
					ArrayList segment = (ArrayList)al[0];
					if(segment.Count > 1)
					{
						PointF p0 = (PointF)segment[0];
						PointF p1 = (PointF)segment[1];
						double dx = (p0.X-p1.X);
						double dy = (p0.Y-p1.Y);
						double dist = dx*dx+dy*dy;
						// find biggest segment:
						for(int i=1; i<segment.Count; i++)
						{
							PointF p_0 = (PointF)segment[i-1];
							PointF p_1 = (PointF)segment[i];	
							dx = (p_0.X-p_1.X);
							dy = (p_0.Y-p_1.Y);
							double curr_dist = dx*dx+dy*dy;
							if(curr_dist > dist)
							{
								dist = curr_dist;
								p0 = p_0;
								p1 = p_1;
							}
						}

						if(dist == 0)
							continue;
						
						PointF [] src_pnts2 = {p0,p1};
						trans.TransformPoints(src_pnts2);
						px = (src_pnts2[0].X+src_pnts2[1].X)/2;
						py = (src_pnts2[0].Y+src_pnts2[1].Y)/2;
			
						angle = (float)(Math.Atan((src_pnts2[0].Y-src_pnts2[1].Y)/(src_pnts2[0].X-src_pnts2[1].X))*180/3.14);
						
						if(this.m_debug)
						{
							graphics.DrawLine(pen,new Point((int)src_pnts2[0].X,(int)src_pnts2[0].Y),
								new Point((int)src_pnts2[1].X,(int)src_pnts2[1].Y));
						}

					}
				}

							
				RotatedRectangle drect = new RotatedRectangle(lrect,px,py,angle);					
				bool intersected = false;
				foreach(RotatedRectangle dr in displayed_labels)
				{
					if(dr.IsIntersected(drect))
						intersected = true;
				}

				if(intersected)
					continue;	
				else
					displayed_labels.Add(drect);
		
				bool do_rotation = true;
				float off_x=0;
				float off_y=0;
				if(Math.Abs(angle) < 5)
				{
					do_rotation = false;
					off_x=px;
					off_y=py;
				}

				if(do_rotation)
				{
					// translate graphics to the text start point:
					graphics.TranslateTransform(px,py);
					// calculate angle:				
					graphics.RotateTransform(angle);
				}

				if(lay.FillLabelBg)
				{
					graphics.FillRectangle(fillBrush,lrect.Left+off_x,
						lrect.Top+off_y,lrect.Width,lrect.Height);
				}

				graphics.DrawString(label,
					drawFont,drawBrush,
					off_x,off_y,drawFormat);
				
				if(this.m_debug)
					graphics.DrawRectangle(pen,lrect.Left+off_x,
						lrect.Top+off_y,lrect.Width,lrect.Height);

				if(do_rotation)
				{
					// translate back
					graphics.RotateTransform(-angle);
					graphics.TranslateTransform(-px,-py);
				}
			}

			long label_end_t = DateTime.Now.Ticks;
			double label_diff = (label_end_t - label_start_t)/10000000.0;
			Trace.Indent();
			string label_msg = "label time["+displayed_labels.Count.ToString()+"]=" + label_diff.ToString() + " sec";
			Trace.WriteLine(label_msg);
			Trace.Unindent();

			drawFont.Dispose();
			drawBrush.Dispose();
			drawFormat.Dispose();
			pen.Dispose();	
			fillBrush.Dispose();
			return true;
		}

		public void LoadImage(Image img)
		{
			if(picture != null)
				picture.Dispose();

			picture = img;

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(BoundingBox()));
	
		}

		public void LoadImage(System.IO.Stream stream)

		{
			if(picture != null)
				picture.Dispose();

			picture = System.Drawing.Image.FromStream(stream);

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(BoundingBox()));
		}

		public void LoadImage(string fname)
		{
			picture = System.Drawing.Image.FromFile(fname);

			if(ModelChangedEvent != null)
				ModelChangedEvent(this,new ModelChangedEventArgs(BoundingBox()));
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
Baranovsky Eduard has been a software developer for more then 10 years. He has an experence in image processing, computer graphics and distributed systems design.

Comments and Discussions