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

Mapview

Rate me:
Please Sign up or sign in to vote.
2.28/5 (19 votes)
6 Jun 20042 min read 79.5K   3.1K   50  
Application is intended to create a 2D canvas from interactive, creating the vector graphics
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Drawing.Imaging;
using System.Data;
using System.Windows.Forms;


/// <summary>
/// Mapview control namespace
/// </summary>
namespace GIS.Geometry
{
	public class Mapview : System.Windows.Forms.UserControl, ICloneable, IPersist
	{
		#region Private members of the Mapview Control
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		/// 
		private System.ComponentModel.Container components = null;
		Image _image; // The current image to be drawn
		Rectangle _rectDst ; // Rendering Rectangle in DC coordinates
		Rectangle _rectSrc ; // ROI of image in image coordinates (0,0, MaxX, MaxY);
		Matrix _cm ; // Current matrix
		private Point[] _fPoint; // To Draw an 'F' character
		private Point _cPoint;
		Point m_StartingPoint, m_EndingPoint;
	//--------------------------------------------
		//
		// For Flicker free painting
		//
		private Rectangle DrawingRect;	// used for tracking of rubberband handle
		private Image tmpView;
		private Image realView;
		private RectangleF tmpRect;
		private RectangleF realRect;
	//--------------------------------------------

		private System.Windows.Forms.ToolTip tp;
		private System.Drawing.Drawing2D.Matrix m_trans;
		private RectangleF viewsize=new RectangleF(0.0F,0.0F,0.0F,0.0F);
		private object m_units;
		private float m_scale = 1;
		private float zoomfactor=1.25F;
		private System.Windows.Forms.HScrollBar h_scroll;
		private System.Windows.Forms.VScrollBar v_scroll;	
		private bool showdirection=false;
		private bool showscale=false;
		
		private Pen rubberlines=new Pen(Color.Red,1);
		private Color backcolor=Color.White;
		private int locationtolarnce=2;
		private int displayscale=1;
		private string text;
		private Font f=new Font("Tahoma",16, FontStyle.Regular,	GraphicsUnit.Pixel);
		private System.Windows.Forms.ContextMenu cmenu;
		private System.Windows.Forms.MenuItem mitem;
		
		private GraphicType m_draw_mode = GraphicType.None;
		private SubGraphicMode m_sub_draw=SubGraphicMode.None;
		private OperationMode m_operation_mode=OperationMode.None;
		private SubOperationMode m_sub_operation=SubOperationMode.All;
		private ZoomType m_zoomtype=ZoomType.Fit;
	
		private float m_start_x = 0;
		private float m_start_y = 0;
		private float m_end_x = 0;
		private float m_end_y = 0;

		private GraphicsCollection m_geom_model=null;

		private int m_curr_selection = -1;
		
		private ArrayList m_current_polygon = new ArrayList();
		private ArrayList m_selected_list = new ArrayList();
		private ArrayList m_copy_list=new ArrayList();
			
		public delegate void CoordChangeEventHandler(object sender, CoordEventArgs e);
		public delegate void ItemEventHandler(object sender, ItemEventArgs e);
		public delegate void GraphicTypeChangedEventHandler(object sender, GraphicArgs e);
		public delegate void OperationChangedEventHandler(object sender, OperationArgs e);
		public delegate void GraphicSelectedHandler();

		public event CoordChangeEventHandler CoordChangeEvent;
		public event ItemEventHandler ItemNewEvent;
		public event ItemEventHandler ItemEnterEvent;
		public event ItemEventHandler ItemLeaveEvent;
		public event GraphicSelectedHandler GraphicSelected;
		
		public event GraphicTypeChangedEventHandler GraphicTypeChanged;
		public event OperationChangedEventHandler OperationChanged;

		private string xml="";
		private int m_drag_handle=-1;
		private int m_current_index=-1;
		private int handlesize=6;

		#endregion
		#region Properties of the Mapview Control
		public object Units
		{
			get{return m_units;}
			set{m_units=value;}
		}
		public System.Drawing.Drawing2D.DashStyle RubberLines
		{
			get {return rubberlines.DashStyle;}
			set{rubberlines.DashStyle=value;}
		}
		
		public bool ShowScale
		{
			get{return showscale;}
			set{showscale=value;}
		}

		public int DisplayScale
		{
			get{return displayscale;}
			set{displayscale=value;}
		}
		
		public Color BackgroundColor
		{
			get{return backcolor;}
			set
			{
				backcolor=value;
				this.BackColor=backcolor;
			}
		}
		public bool ShowDirection
		{
			get{return showdirection;}
			set{showdirection=value;}
		}

		public int LocationTolerance
		{
			get{return locationtolarnce;}
			set{locationtolarnce=value;}
		}

		public float ZoomFactor
		{
			get{return zoomfactor;}
			set{zoomfactor=value;}
		}
		public void Model(GraphicsCollection objIn)
		{
			if (objIn!=null)
			{
				m_geom_model=objIn;
				m_geom_model.ItemChangedEvent+=new GIS.Geometry.GraphicsCollection.ItemChangedEventHandler(OnModelChanged);
				m_geom_model.ModelChangedEvent+=new GIS.Geometry.GraphicsCollection.ModelChangedEventHandler(OnModelChanged);		
			}
		}
		public GraphicsCollection Model()
		{
			return m_geom_model;
		}
		/// <summary>
		/// initilize graphic object drawing mode.
		/// new graphic object is drawn while mouse moving with left key pressed.
		/// New graphic object is added to map on mouse release.
		/// </summary>
		///
		public GraphicType CurrentGraphicType
		{
			get{return m_draw_mode;}
			set
			{
				m_draw_mode=value;
				m_current_polygon.Clear();
				// Generate Graphic Type Changed event
				if(GraphicTypeChanged != null) GraphicTypeChanged(this,new GraphicArgs(m_draw_mode));
			}
		}
		/// <summary>
		/// initilize graphic object operation mode.
		/// new graphic object operation is drawn while mouse moving with left key pressed.
		/// New graphic object operation is added to map on mouse release.
		/// </summary>
		///
		public OperationMode CurrentOperation
		{
			get{return m_operation_mode;}
			set
			{
				m_operation_mode=value;
				// Generate Graphic Type Changed event
				if(OperationChanged != null) OperationChanged(this,new OperationArgs(m_operation_mode));
				Invalidate();
			}
		}
		/// <summary>
		/// initilize graphic object operation mode.
		/// new graphic object operation is drawn while mouse moving with left key pressed.
		/// New graphic object operation is added to map on mouse release.
		/// </summary>
		///
		public ZoomType CurrentZoomType
		{
			get{return m_zoomtype;}
			set
			{
				m_zoomtype=value;
				// Generate Graphic Type Changed event
				if(OperationChanged != null) OperationChanged(this,new OperationArgs(m_operation_mode));
				Invalidate();
			}
		}
		#endregion
		#region Constructor of Mapview Controls
		/// <summary>
		/// constructor
		/// </summary>
		public Mapview()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			// TODO: Add any initialization after the InitForm call
			//viewsize = new RectangleF();
			m_trans = new System.Drawing.Drawing2D.Matrix();
			m_scale = 1;
			realRect= new Rectangle();
			tmpRect= new Rectangle();
		}

		public Mapview(Mapview mv)
		{
		}
		#endregion
		#region Methods of ICloneable
		public object Clone()
		{ 
			return new Mapview( this ); 
		}
		#endregion
		#region Methods of Mapview Control
			#region Transformation operations
			public void SaveSettings()
			{
				
			}
			public IMapviewObject GetItem(int indx)
			{
				return m_geom_model.GetItem(indx);
			}

			public object GetitemObject(int i)
			{
				return m_geom_model.GetItemObject(i);
			}

			public int [] GetSelected()
			{
				return m_geom_model.GetSelected();
			}

			public int Add(IMapviewObject item)
			{
				return m_geom_model.Add(item);
			}

			public PointF ClientToReal(PointF pnt)
			{
				System.Drawing.Drawing2D.Matrix inv_trans = m_trans.Clone();
				inv_trans.Invert();
				PointF[] points = {new PointF(pnt.X,pnt.Y)};
				inv_trans.TransformPoints(points);
				return points[0];
			}
			public Rectangle RealToClient(RectangleF rect)
			{
				return RealToClient(new PointF(rect.X,rect.Y),
					rect.Width, rect.Height);
			}
			public Rectangle RealToClient(PointF pnt,float w,float h)
			{
				System.Drawing.Drawing2D.Matrix inv_trans = m_trans.Clone();
				PointF[] points = {new PointF(pnt.X,pnt.Y),new PointF(pnt.X+w,pnt.Y+h)};
				inv_trans.TransformPoints(points);
				Rectangle rect = new Rectangle((int)points[0].X,(int)points[0].Y,
					(int)(points[1].X-points[0].X)+1,
					(int)(points[1].Y-points[0].Y)+1);
				return rect;
			}
			#endregion
			#region Mouse Events
			private void MapClick(object sender,EventArgs e)
			{
				if (m_operation_mode==GIS.Geometry.OperationMode.None)
				{
					Select(0);
				}
			}
			protected override void OnMouseEnter(EventArgs e)
			{
				this.Focus();
			}
			private void MapMouseMove(object sender, MouseEventArgs e)
			{
				PointF ep = ClientToReal(new PointF(e.X,e.Y));
				// Generate Coordinates Changed event
				if(CoordChangeEvent != null) CoordChangeEvent(this,new CoordEventArgs(ep.X,ep.Y,0,0,0));
				Graphics graph = this.CreateGraphics();
				int x = Math.Min((int)m_start_x,(int)e.X);
				int y = Math.Min((int)m_start_y,(int)e.Y);
				int w = (int)(e.X-m_start_x<0.0?(int)m_start_x-e.X:(int)e.X-m_start_x);
				int h = (int)(e.Y-m_start_y<0.0?(int)m_start_y-e.Y:(int)e.Y-m_start_y);

				Rectangle c1 = new Rectangle(x-6,y-6,w+12,h+12);
				#region Graphic objects with more than 2 points
				if (m_draw_mode==GIS.Geometry.GraphicType.Polyline || 
					m_draw_mode==GIS.Geometry.GraphicType.Polygon  || 
					m_draw_mode==GIS.Geometry.GraphicType.Curve    ||
					m_draw_mode==GIS.Geometry.GraphicType.Boundary ||
					m_draw_mode==GIS.Geometry.GraphicType.Spline   ||
					m_draw_mode==GIS.Geometry.GraphicType.Freeform)
				{
					Draw(e);
					return;
				}
				#endregion
				if(e.Button != MouseButtons.Left)return;
				if( Math.Abs(e.X-m_end_x) < 2 && Math.Abs(e.Y-m_end_y) < 2)
					return;
				#region Operations on the objects
				switch(m_operation_mode)
				{
						#region For Move Operation
					case GIS.Geometry.OperationMode.Move:
						if (e.Button == MouseButtons.Left)
						{				
							// calculate Move delta
							PointF p_start = new PointF(m_start_x,m_start_y);
							PointF p_end = new PointF(m_end_x,m_end_y);

							PointF p_start_real = ClientToReal(p_start);
							PointF p_end_real = ClientToReal(p_end);

							float dx = p_start_real.X-p_end_real.X;
							float dy = p_start_real.Y-p_end_real.Y;				
							// Move the selected objects
							m_geom_model.MoveBy(dx,dy);
							Invalidate();
							m_end_x = e.X;
							m_end_y = e.Y;
							return;
						}
						break;
						#endregion
						#region For Selection Operation
					case GIS.Geometry.OperationMode.Selection:
					case GIS.Geometry.OperationMode.Edit:
					case GIS.Geometry.OperationMode.Zoom:
							Invalidate(c1);
							Update();
							graph.DrawRectangle(rubberlines,x,y,w,h);
							break;
						#endregion
//						#region For Zoom Operation
//					case GIS.Geometry.OperationMode.Zoom:
//						goto case GIS.Geometry.OperationMode.Selection;
//						#endregion
					case GIS.Geometry.OperationMode.Pan:
						Matrix ScreenToImg = GeoUtil.Swap(_rectDst, _rectSrc);
						m_EndingPoint.X = e.X;
						m_EndingPoint.Y = e.Y;
						Point[] Vector = new Point[2];
						Vector[0] = m_EndingPoint;
						Vector[1] = m_StartingPoint;
						ScreenToImg.TransformPoints(Vector);
						Point PtDelta = new Point(Vector[1].X-Vector[0].X+_rectSrc.X, 
							Vector[1].Y-Vector[0].Y+_rectSrc.Y);

						if((PtDelta.X <0) || (PtDelta.X + _rectSrc.Width > _image.Width))
							PtDelta.X=0;
						else
							PtDelta.X-=_rectSrc.X;

						if((PtDelta.Y <0) || (PtDelta.Y + _rectSrc.Height > _image.Height))
							PtDelta.Y=0;
						else
							PtDelta.Y-=_rectSrc.Y;

						_rectSrc.Offset(PtDelta);
						
						m_StartingPoint = m_EndingPoint;

						Refresh();
						break;
					case GIS.Geometry.OperationMode.Arrange:
						break;
					case GIS.Geometry.OperationMode.Copy:
						goto case GIS.Geometry.OperationMode.Selection;
					case GIS.Geometry.OperationMode.Rotate:

					default:
						break;
				}
				#endregion
				#region Graphic Obejects with 2 points
				switch(m_draw_mode)
				{
					case GIS.Geometry.GraphicType.Line:
					{					
						Invalidate(c1);
						Update();
						graph.DrawLine(rubberlines,(int)m_start_x,
							(int)m_start_y,
							(int)e.X,
							(int)e.Y);
					}
						break;
				
					case GIS.Geometry.GraphicType.Rectangle:
					{					
						Invalidate(c1);
						Update();		
						graph.DrawRectangle(rubberlines,x,y,w,h);	
					}
						break;
					case GIS.Geometry.GraphicType.Elipse:
					{					
						Invalidate(c1);
						Update();		
						graph.DrawEllipse(rubberlines,x,y,w,h);	
					}
						break;
					case GIS.Geometry.GraphicType.Circle:
					{					
						Invalidate(c1);
						Update();		
						graph.DrawEllipse(rubberlines,x,y,w,w);	
					}
						break;
					case GIS.Geometry.GraphicType.Polyline:
						#region Polyline
						if(m_current_polygon.Count>1)
						{					
							//Invalidate();
							Update();
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawLines(rubberlines,points);	
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Polygon:
						#region polygon
						if(m_current_polygon.Count>1)
						{					
							Invalidate(c1);
							Update();
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawPolygon(rubberlines,points);	
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Spline:
						#region Spline
						if(m_current_polygon.Count>1)
						{						
							Invalidate(c1);
							Update();
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawBeziers(rubberlines,points);	
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Curve:
						#region Curve
						if(m_current_polygon.Count>3)
						{						
							Invalidate(c1);
							Update();
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawCurve(rubberlines,points);
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Freeform:
						break;
					case GIS.Geometry.GraphicType.UserDefined:
						///TODO: Yet to be planned
						break;
					case GIS.Geometry.GraphicType.Text:
						graph.DrawString(text,f,new SolidBrush(Color.Red),c1,System.Drawing.StringFormat.GenericDefault);
						break;
					default:
						break;
				}
				#endregion
				m_end_x = e.X;
				m_end_y = e.Y;
			}
			private void MapMouseDown(object sender, MouseEventArgs e)
			{	
				m_start_x = e.X;
				m_start_y = e.Y;
				#region For Context menus
				if (e.Button==MouseButtons.Right)
				{
					switch(m_draw_mode)
					{
						case GIS.Geometry.GraphicType.Line:
							cmenu.MenuItems.Add("Cut");
							cmenu.MenuItems.Add("Copy");
							cmenu.MenuItems.Add("Paste");
							cmenu.MenuItems.Add("-");
							cmenu.MenuItems.Add("Edit Points");
							break;
						case GIS.Geometry.GraphicType.Circle:
							break;
						case GIS.Geometry.GraphicType.Arc:
							break;
						case GIS.Geometry.GraphicType.None:
							for(int i=0; i<cmenu.MenuItems.Count-1; i++)
							{
								cmenu.MenuItems.RemoveAt(i);
							}
							break;
					}
				}
				#endregion
				#region For Resize handles
				if (m_operation_mode==GIS.Geometry.OperationMode.Edit)
				{
					if (m_drag_handle!=-1)
					{
						IMapviewObject item=m_geom_model.GetByIndex(m_current_index);
						for (int i=0; i<item.Vertices.Length-1; i++)
						{
							if (Math.Abs(item.Vertices[i].X - e.X) < handlesize/2 && 
								Math.Abs(item.Vertices[i].Y - e.Y) < handlesize/2)
							{
								m_drag_handle = i;
								this.Cursor= Cursors.Cross;
								break;
							}
						}
					}
				}
				#endregion
				if(m_draw_mode == GIS.Geometry.GraphicType.None)
					return;

				if(m_draw_mode == GIS.Geometry.GraphicType.Polygon || 
					m_draw_mode==GIS.Geometry.GraphicType.Polyline  ||
					m_draw_mode == GIS.Geometry.GraphicType.Curve   ||
					m_draw_mode == GIS.Geometry.GraphicType.Spline  ||	
					m_draw_mode == GIS.Geometry.GraphicType.Freeform  )
				{
					if (m_operation_mode==GIS.Geometry.OperationMode.Edit)
					{
//						m_current_polygon.Insert(new PointF(e.X,e.Y));
					}
					else
					{
						m_current_polygon.Add(new PointF(e.X,e.Y));
					}
				}
				
			}
			private void MapMouseUp(object sender, MouseEventArgs e)
			{	
				#region Operations
				switch(m_operation_mode)
				{
					case GIS.Geometry.OperationMode.Selection:
						Select(-1);
						Invalidate();
						break;
					case GIS.Geometry.OperationMode.Edit:
						Edit();
						Invalidate();
						break;
					case GIS.Geometry.OperationMode.Arrange:
						Invalidate();
						break;
					case GIS.Geometry.OperationMode.Copy:
						goto case GIS.Geometry.OperationMode.Selection;
					case GIS.Geometry.OperationMode.Rotate:
						Invalidate();
						break;
					case GIS.Geometry.OperationMode.Zoom:
						Zoom();
						Invalidate();
						break;
					default:
						break;
				}
				#endregion
				#region For Graphics
				if(m_draw_mode == GIS.Geometry.GraphicType.None)
					return;
				
				System.Drawing.Drawing2D.Matrix inv_trans = m_trans.Clone();
				inv_trans.Invert();
				PointF [] points = {new PointF(m_start_x,m_start_y), 
									new PointF(m_end_x,m_end_y)};
				inv_trans.TransformPoints(points);
				int curr_item_id = -1,w,h;

				switch(m_draw_mode)
				{
					case GIS.Geometry.GraphicType.Point:
						curr_item_id = m_geom_model.Add(new PointObject(points[0].X,points[0].Y));
						break;
					case GIS.Geometry.GraphicType.Line:
						curr_item_id = m_geom_model.Add(new LineObject(points[0].X,points[0].Y,	points[1].X,points[1].Y));
						break;
					case GIS.Geometry.GraphicType.Rectangle:
						GeoUtil.Swap(ref points);
						w = (int)(points[1].X - points[0].X);
						h = (int)(points[1].Y - points[0].Y);		
						curr_item_id = m_geom_model.Add(new RectangleObject(points[0].X,points[0].Y,w,h));
						break;
					case  GIS.Geometry.GraphicType.Elipse:
						GeoUtil.Swap(ref points);
						w = (int)(points[1].X - points[0].X);
						h = (int)(points[1].Y - points[0].Y);
						curr_item_id = m_geom_model.Add(new EllipseObject(points[0].X,points[0].Y,w,h));
						break;
					case GIS.Geometry.GraphicType.Circle:
						GeoUtil.Swap(ref points);
						w = (int)(points[1].X - points[0].X);
						curr_item_id = m_geom_model.Add(new CircleObject(points[0].X,points[0].Y,w,w));
						break;
					case GIS.Geometry.GraphicType.Text:
						curr_item_id=m_geom_model.Add(new TextObject(points[0].X, points[0].Y,text,f));
						return;
				}

				if(m_draw_mode != GIS.Geometry.GraphicType.Polygon  || 
					m_draw_mode != GIS.Geometry.GraphicType.Polyline ||
					m_draw_mode != GIS.Geometry.GraphicType.Curve    ||	
					m_draw_mode != GIS.Geometry.GraphicType.Spline   ||
					m_draw_mode != GIS.Geometry.GraphicType.Freeform ||	
					m_operation_mode != GIS.Geometry.OperationMode.Move)
				{
					m_start_x = 0; 
					m_start_y = 0;
				}
				#endregion
				#region Context Menu
				if (e.Button==MouseButtons.Right)
				{
					this.ContextMenu=cmenu;
				}
				#endregion
				#region Notify the others by raising the event
				if(ItemNewEvent != null && (
					m_draw_mode == GIS.Geometry.GraphicType.Line		||
					m_draw_mode == GIS.Geometry.GraphicType.Rectangle	||
					m_draw_mode == GIS.Geometry.GraphicType.Elipse		||
					m_draw_mode == GIS.Geometry.GraphicType.Circle		||
					m_draw_mode == GIS.Geometry.GraphicType.Point		||
					m_draw_mode == GIS.Geometry.GraphicType.Text		
					))
					ItemNewEvent(this,new ItemEventArgs(curr_item_id));
				#endregion
			}
			protected override void OnDoubleClick(EventArgs e)
			{
				Close();
			}
			#endregion
			#region Key Events
			protected override void OnKeyDown(KeyEventArgs e)
			{
	//			if (e.Modifiers==Keys.ControlKey  && System.Windows.Forms.Keys.A)
	//					BeginSelection(false);				
			}
			protected override void OnKeyPress(KeyPressEventArgs e)
			{
			
			}
			protected override void OnKeyUp(KeyEventArgs e)
			{
				if (m_draw_mode==GIS.Geometry.GraphicType.Text)
				{
					text+=e.KeyCode;
				}
				switch(e.KeyData)
				{
					case System.Windows.Forms.Keys.Escape:
						Reset();
						break;
					case System.Windows.Forms.Keys.Delete:
						Delete();
						break;
				}
				Invalidate();
			}
			#endregion
			#region Paint Events
			private void MapPaint(object sender,PaintEventArgs e)
			{
				RefreshView();
			}
			public void OnModelChanged(object sender, ItemEventArgs e)
			{
				RefreshView();
			}
			 
			private void OnPaintBackground(PaintEventArgs e) 
			{
				//
			}
			#endregion
			#region Zoom, Pan Events
			private PointF GetCenter()
			{
				// Draw image center marker
				System.Drawing.Drawing2D.Matrix inv_trans = m_trans.Clone();
				inv_trans.Invert();
		
				// create 0,0 and width,height points
				PointF[] points = {new PointF(0,0),new PointF(this.Width,this.Height)};
				inv_trans.TransformPoints(points);
							
				int x0 = (int)(points[0].X+points[1].X)/2;
				int y0 = (int)(points[0].Y+points[1].Y)/2;

				return new PointF(x0,y0);
			}
			public void Zoom()
			{
				float shift_x = this.Width/2;
				float shift_y = this.Height/2;
				//tmpRect= viewsize;
				realRect=m_geom_model.BoundingBox();
				Matrix ScreenToImg = GeoUtil.Swap(tmpRect, realRect);
				Point[] Pts = new Point[2];
				Pts[0] = new Point((int)m_end_x,(int)m_end_y);
				Pts[1] = new Point((int)m_start_x,(int)m_start_y);
				ScreenToImg.TransformPoints(Pts);
				switch(m_zoomtype)
				{
					case GIS.Geometry.ZoomType.In:
						m_scale += zoomfactor;
						m_trans.Scale(zoomfactor, zoomfactor, System.Drawing.Drawing2D.MatrixOrder.Append);
						m_trans.Translate(-shift_x, -shift_y, System.Drawing.Drawing2D.MatrixOrder.Append);
						break;
					case GIS.Geometry.ZoomType.Out:
						m_scale -= zoomfactor;
						m_trans.Scale(zoomfactor, zoomfactor, System.Drawing.Drawing2D.MatrixOrder.Append);
						m_trans.Translate(zoomfactor, zoomfactor, System.Drawing.Drawing2D.MatrixOrder.Append);			
						break;
					case GIS.Geometry.ZoomType.Extents:
						break;
					case GIS.Geometry.ZoomType.Center:
						break;
					case GIS.Geometry.ZoomType.Pan:
						Point PtDelta = new Point(Pts[1].X-Pts[0].X+realRect.X, 
							Pts[1].Y-Pts[0].Y+realRect.Y);
						if((PtDelta.X <0) || (PtDelta.X + realRect.Width > realView.Width))
							PtDelta.X=0;
						else
							PtDelta.X-=realRect.X;
						if((PtDelta.Y <0) || (PtDelta.Y + realRect.Height > realView.Height))
							PtDelta.Y=0;
						else
							PtDelta.Y-=realRect.Y;
						realRect.Offset(PtDelta);
						m_StartingPoint = m_EndingPoint;
						Refresh();
						break;
					case GIS.Geometry.ZoomType.Window:
						// Limits Maximum Zoom
						if(pts[1].X - Pts[0].X>10)
						if(Pts[1].Y - Pts[0].Y>10)
						{
							realRect.Location = Pts[0];
							realRect.Width = Pts[1].X - Pts[0].X;
							realRect.Height = Pts[1].Y - Pts[0].Y;
							Refresh();
						}
						break;
					case GIS.Geometry.ZoomType.Fit:
						Fit();
						break;
				}
				UpdateScroll();
				RefreshView();
			}
	
			public void Fit()
			{
				viewsize = m_geom_model.BoundingBox();
				if(viewsize.Width == 0 || viewsize.Height == 0)
					return;
				m_trans.Reset();
				m_trans.Translate(viewsize.X,viewsize.Y);
				m_trans.Scale(this.Width/viewsize.Width,this.Height/viewsize.Height);
				//Invalidate();
				RefreshView();
			}
			public void Pan(Point p0, Point p1)
			{
				Matrix matPan = m_trans.Clone();
				//			m_EndingPoint.X = (int)p1.X;
				//			m_EndingPoint.Y = (int)p1.Y;
				//			m_StartingPoint.X=(int)p0.X;
				//			m_StartingPoint.Y=(int)p0.Y;
				Point[] Vector = new Point[2];
				Vector[0] = (Point)p0; //m_EndingPoint;
				Vector[1] = (Point)p1; //m_StartingPoint;
				matPan.TransformPoints(Vector);
				PointF PtDelta = new PointF(Vector[1].X-Vector[0].X+viewsize.X, 
					Vector[1].Y-Vector[0].Y+viewsize.Y);

				if((PtDelta.X <0) || (PtDelta.X + viewsize.Width > viewsize.Width))
					PtDelta.X=0;
				else
					PtDelta.X-=viewsize.X;
				if((PtDelta.Y <0) || (PtDelta.Y + viewsize.Height > viewsize.Height))
					PtDelta.Y=0;
				else
					PtDelta.Y-=viewsize.Y;
				viewsize.Offset(PtDelta);
				Refresh();
			}
			private void UpdateScroll()
			{
				// calculate and update H and V scroll values:
				if(h_scroll != null)
				{
					int val = (int)(-m_trans.OffsetX/m_scale/viewsize.Width*100);
					if(val < 0)
						val = 0; 				
					if(val > 99)
						val = 99;
					h_scroll.Value = val+1;
				}

				if(v_scroll != null)
				{
					int val = (int)(-m_trans.OffsetY/m_scale/viewsize.Height*100);
					if(val < 1)
						val = 1; 				
					if(val > 100)
						val = 100;
					v_scroll.Value = val-1;
				}
			}
			public void LoadImage(string fname)
			{
				m_geom_model.LoadImage(fname);
				viewsize = m_geom_model.BoundingBox();
				RefreshView();
			}

			public void HorizontalScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
			{		
				viewsize = m_geom_model.BoundingBox();
				float off_x = m_trans.OffsetX;
				float shift = viewsize.Width*e.NewValue/100*m_scale+off_x;
				m_trans.Translate(-shift, 0, System.Drawing.Drawing2D.MatrixOrder.Append);
				RefreshView();
			}
			public void VerticalScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
			{
				viewsize = m_geom_model.BoundingBox();
				float off_y = m_trans.OffsetY;
				float shift = viewsize.Height*e.NewValue/100*m_scale+off_y;
				m_trans.Translate(0, -shift, System.Drawing.Drawing2D.MatrixOrder.Append);
				RefreshView();
			}
			public void UpdateView(Image i)
			{	// draws image of the Frame.
				Graphics g = this.CreateGraphics();
				g.DrawImage(i, this.ClientRectangle);
				g.Dispose();
			}
			private void RefreshView()
			{	// erase the main image and redraw all the rectangles from the list.
				realView.Dispose();
				realView = new Bitmap(this.ClientRectangle.Width,
					this.ClientRectangle.Height);
				Graphics g = Graphics.FromImage(realView);
				Brush BrushTemp = new SolidBrush(this.BackColor);
				g.FillRectangle(BrushTemp, this.ClientRectangle);
				if (m_geom_model!=null)
				{
					m_geom_model.Draw(g,m_trans);
				}
				BrushTemp.Dispose();
				g.Dispose();
				UpdateView(realView);
			}
			#endregion
			#region Operations like Select, Move, Delete, Rotate, Scale...
			private void Select(int intType)
			{
					PointF [] points = {new PointF(m_start_x,m_start_y), 
										   new PointF(m_end_x,m_end_y)};
					int i=GeoUtil.Swap(ref points);
					PointF c_pnt = new PointF(m_start_x,m_start_y);
					PointF c_pnt1 = new PointF(m_end_x,m_end_y);
					PointF r_pnt = ClientToReal(c_pnt);
					PointF r_pnt1 = ClientToReal(c_pnt1);
					float dist = r_pnt1.X-r_pnt.X;
					Rectangle rect = new Rectangle((int)points[0].X,(int)points[0].Y,
						(int)(points[1].X-points[0].X)+1,
						(int)(points[1].Y-points[0].Y)+1);
				for (int indx=0; indx<m_geom_model.Count; indx++)
				{
					IMapviewObject item = m_geom_model.GetByIndex(indx);
					if (intType==1)
					{
						item.Select(true);
					}
					else if(intType==0)
					{
						item.Select(false);
					}
					else
					{		
						switch(i)
						{
							case 1: // Crossing the window :: Intersection,
								if(rect.IntersectsWith(item.BoundingBox()))
									item.Select(true);
								break;
							case 2://Except this
								if(rect.IntersectsWith(item.BoundingBox()))
									item.Select(false);
								break;
							case 3://All :: Union
								item.Select(true);
								break;
							case 4: // Inside the window ::	In,
								if (rect.Contains(item.BoundingBox()))
									item.Select(true);
								break;
						}
					}
				}
				// Generate Object selected event
				if(GraphicSelected != null) GraphicSelected();
			}
			private void Move(MouseEventArgs e)
			{
				m_curr_selection = -1;
				PointF c_pnt = new PointF(e.X,e.Y);
				PointF c_pnt1 = new PointF(e.X+5,e.Y);
				PointF r_pnt = ClientToReal(c_pnt);
				PointF r_pnt1 = ClientToReal(c_pnt1);
				float dist = r_pnt1.X-r_pnt.X;

				for(int indx=0; indx < m_geom_model.Count; indx++)
				{					
					IMapviewObject item = m_geom_model.GetByIndex(indx);
					if(item.IsSelected())
					{
						if(!item.IsObjectAt(r_pnt,dist))
						{							
							if(m_selected_list.IndexOf(indx,0,m_selected_list.Count) == -1)
							{
								item.Select(false);
								Invalidate(RealToClient(item.BoundingBox()));
								if(ItemLeaveEvent != null)
									ItemLeaveEvent(this,new ItemEventArgs(indx));
							}							
						}
						else
						{
							m_curr_selection = m_geom_model.GetKey(indx);
						}
					}
					else
					{
						if(item.IsObjectAt(r_pnt,dist))
						{
							m_curr_selection = m_geom_model.GetKey(indx);
							item.Select(true);
							Invalidate(RealToClient(item.BoundingBox()));
							// To notify the index of the current selected graphic index
							if(ItemEnterEvent != null)	ItemEnterEvent(this,new ItemEventArgs(indx));
						}
					}
						
				}
				m_end_x = e.X;
				m_end_y = e.Y;
			}

			private void Draw(MouseEventArgs e)
			{
				RefreshView();
				Graphics graph = this.CreateGraphics();
				int x = Math.Min((int)m_start_x,(int)e.X);
				int y = Math.Min((int)m_start_y,(int)e.Y);
				int w = (int)(e.X-m_start_x<0.0?(int)m_start_x-e.X:(int)e.X-m_start_x);
				int h = (int)(e.Y-m_start_y<0.0?(int)m_start_y-e.Y:(int)e.Y-m_start_y);
				Rectangle c1 = new Rectangle(x-6,y-6,w+12,h+12);
				switch(m_draw_mode)
				{
					case GIS.Geometry.GraphicType.Polyline:
						#region Polyline
						if(m_current_polygon.Count>1)
						{					
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawLines(rubberlines,points);
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Polygon:
						#region polygon
						if(m_current_polygon.Count>1)
						{					
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawPolygon(rubberlines,points);	
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Spline:
						#region Spline
						if(m_current_polygon.Count>1)
						{						
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawBeziers(rubberlines,points);	
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Curve:
						#region Curve
						if(m_current_polygon.Count>3)
						{						
							m_current_polygon[m_current_polygon.Count-1] = new PointF(e.X,e.Y);
							Point[] points = new Point[m_current_polygon.Count];
							for(int i=0; i<m_current_polygon.Count; i++)
							{
								int x1 = (int)((PointF)m_current_polygon[i]).X;
								int y1 = (int)((PointF)m_current_polygon[i]).Y;
								points[i] = new Point(x1,y1);
							}
							graph.DrawCurve(rubberlines,points);
						}
						break;
						#endregion
					case GIS.Geometry.GraphicType.Freeform:
						break;
					case GIS.Geometry.GraphicType.UserDefined:
						///TODO: Yet to be planned
						break;
					case GIS.Geometry.GraphicType.Text:
						graph.DrawString(text,f,new SolidBrush(Color.Red),c1,System.Drawing.StringFormat.GenericDefault);
						break;
					default:
						break;
				}
			}
			private void Close()
			{
				m_start_x = 0; 
				m_start_y = 0;
				if (m_draw_mode==GIS.Geometry.GraphicType.Polyline ||
					m_draw_mode==GIS.Geometry.GraphicType.Polygon  ||
					m_draw_mode== GIS.Geometry.GraphicType.Curve   ||	
					m_draw_mode== GIS.Geometry.GraphicType.Spline  ||	
					m_draw_mode== GIS.Geometry.GraphicType.Freeform )
				{
					System.Drawing.Drawing2D.Matrix inv_trans = m_trans.Clone();
					inv_trans.Invert();

					PointF [] points = new PointF[m_current_polygon.Count];
					m_current_polygon.CopyTo(0,points,0,m_current_polygon.Count);

					inv_trans.TransformPoints(points);

					for(int i=0; i<m_current_polygon.Count; i++)
						m_current_polygon[i] = points[i];	
					int item_id =0;
					switch (m_draw_mode)
					{
						case GIS.Geometry.GraphicType.Polyline:
							item_id = m_geom_model.Add(new PolylineObject(m_current_polygon));
							break;
						case GIS.Geometry.GraphicType.Polygon:
							item_id = m_geom_model.Add(new PolygonObject(m_current_polygon));
							break;
						case GIS.Geometry.GraphicType.Curve:
							item_id = m_geom_model.Add(new CurveObject(m_current_polygon));
							break;
						case GIS.Geometry.GraphicType.Spline:
							item_id = m_geom_model.Add(new SplineObject(m_current_polygon));
							break;
						case GIS.Geometry.GraphicType.Freeform:
							item_id = m_geom_model.Add(new FreeFormObject(m_current_polygon));
							break;
					}

					if(ItemNewEvent != null)
						ItemNewEvent(this,new ItemEventArgs(item_id));	
				}
				Invalidate();
				m_current_polygon.Clear();
			}
			public void Edit()
			{
				PointF [] points = {new PointF(m_start_x,m_start_y), 
										new PointF(m_end_x,m_end_y)};
				int i=GeoUtil.Swap(ref points);
				PointF c_pnt = new PointF(m_start_x,m_start_y);
				PointF c_pnt1 = new PointF(m_end_x,m_end_y);
				PointF r_pnt = ClientToReal(c_pnt);
				PointF r_pnt1 = ClientToReal(c_pnt1);
				float dist = r_pnt1.X-r_pnt.X;
				Rectangle rect = new Rectangle((int)points[0].X,(int)points[0].Y,
					(int)(points[1].X-points[0].X)+1,
					(int)(points[1].Y-points[0].Y)+1);
				for (int indx=0; indx<m_geom_model.Count; indx++)
				{
					IMapviewObject item = m_geom_model.GetByIndex(indx);
					switch(i)
					{
						case 1: // Crossing the window :: Intersection,
							if(rect.IntersectsWith(item.BoundingBox()))
								item.IsEdit=true;
								m_current_index=i;
								return;
						case 2://Except this
							if(rect.IntersectsWith(item.BoundingBox()))
								item.IsEdit=true;
								m_current_index=i;
								return;
						//case 3://All :: Union
							//item.IsEdit=true;
						//	return;
						case 4: // Inside the window ::	In,
							if (rect.Contains(item.BoundingBox()))
								item.IsEdit=true;
								m_current_index=i;
								return;
					}
				}
			}
			public void Delete()
			{
				m_geom_model.Delete();
				RefreshView();
			}
			public void Scale()
			{
				m_geom_model.Scale();			
				RefreshView();
			}
			public void Rotate()
			{
				m_geom_model.Rotate();			
				RefreshView();
			}
			public void RotateAt()
			{
				m_geom_model.RotateAt();			
				RefreshView();
			}
			public virtual void Reset()
			{
				m_draw_mode=GIS.Geometry.GraphicType.None;
				m_current_polygon.Clear();
				m_operation_mode=GIS.Geometry.OperationMode.None;
				m_current_index=-1;
			}
			#endregion
		#endregion
		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Mapview));	

			realView = new Bitmap(this.ClientRectangle.Width,
				this.ClientRectangle.Height);

			Graphics GraphicsTemp = Graphics.FromImage(realView);
			Brush BrushTemp = new SolidBrush(this.BackColor);
			GraphicsTemp.FillRectangle(BrushTemp, this.ClientRectangle);
			// Disposing
			BrushTemp.Dispose();
			GraphicsTemp.Dispose();



			this.h_scroll = new System.Windows.Forms.HScrollBar();
			this.v_scroll = new System.Windows.Forms.VScrollBar();
			this.cmenu = new System.Windows.Forms.ContextMenu();
			this.mitem = new System.Windows.Forms.MenuItem();
			this.SuspendLayout();
			// 
			// h_scroll
			// 
			this.h_scroll.Anchor = ((System.Windows.Forms.AnchorStyles)(resources.GetObject("h_scroll.Anchor")));
			this.h_scroll.Dock = ((System.Windows.Forms.DockStyle)(resources.GetObject("h_scroll.Dock")));
			this.h_scroll.Name = "h_scroll";
			this.h_scroll.Minimum=0;
			this.h_scroll.Maximum=100;
			this.h_scroll.Value=50;
			this.h_scroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.HorizontalScroll);
			// 
			// v_scroll
			// 
			this.v_scroll.Anchor = ((System.Windows.Forms.AnchorStyles)(resources.GetObject("v_scroll.Anchor")));
			this.v_scroll.Dock = ((System.Windows.Forms.DockStyle)(resources.GetObject("v_scroll.Dock")));
			this.v_scroll.Name = "v_scroll";
			this.v_scroll.Minimum=0;
			this.v_scroll.Maximum=100;
			this.v_scroll.Value=50;
			this.v_scroll.Scroll += new System.Windows.Forms.ScrollEventHandler(this.VerticalScroll);
			// 
			// cmenu
			// 
			this.cmenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {this.mitem});
			this.cmenu.RightToLeft = ((System.Windows.Forms.RightToLeft)(resources.GetObject("cmenu.RightToLeft")));
			// 
			// mitem
			// 
			this.mitem.Enabled = ((bool)(resources.GetObject("mitem.Enabled")));
			this.mitem.Index = 0;
			this.mitem.Shortcut = ((System.Windows.Forms.Shortcut)(resources.GetObject("mitem.Shortcut")));
			this.mitem.ShowShortcut = ((bool)(resources.GetObject("mitem.ShowShortcut")));
			this.mitem.Text = resources.GetString("mitem.Text");
			this.mitem.Visible = ((bool)(resources.GetObject("mitem.Visible")));
			///
			///Tooltip
			///

			// 
			// Mapview
			// 
			this.ContextMenu = this.cmenu;
			this.Controls.Add(this.h_scroll);
			this.Controls.Add(this.v_scroll);
			this.BackgroundColor=backcolor;
			this.BackColor=backcolor;
			this.Name = "Mapview";
			this.Paint += new System.Windows.Forms.PaintEventHandler(this.MapPaint);
			this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MapMouseMove);
			this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MapMouseDown);
			this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MapMouseUp);
			this.Click+=new EventHandler(this.MapClick);
			this.GraphicSelected+=new GraphicSelectedHandler(this.Edit);
	
			this.ResumeLayout(false);
			m_trans = new System.Drawing.Drawing2D.Matrix();
			m_scale = 1;
			
			//SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint,true);
			//SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
			//SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer,true);

		}
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#endregion
		#region IPersist Members

		public string ToXML
		{
			get{return m_geom_model.ToXML;}
			set{xml=value;}
		}

		public string ToVML
		{
			get{return m_geom_model.ToVML;}
			set{xml=value;}
		}

		public string ToGML
		{
			get{return m_geom_model.ToGML;}
			set{xml=value;}
		}

		public string ToSVG
		{
			get{return m_geom_model.ToSVG;}
			set{xml=value;}
		}

		#endregion
	}
}

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
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions