Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Statistical parsing of English sentences

, 13 Dec 2006
Shows how to generate parse trees for English language sentences, using a C# port of OpenNLP, a statistical natural language parsing library.
englishparsing_bin.zip
Lithium.dll
ModelConverter.exe
OpenNLP Tools.chm
OpenNLP.dll
ParseTree.exe
SharpEntropy.dll
ToolsExample.exe
englishparsing_net2_0_bin.zip
ToolsExample.exe
Lithium.dll
ModelConverter.exe
OpenNLP Tools.chm
OpenNLP.dll
ParseTree.exe
SharpEntropy.dll
englishparsing_net2_0_src.zip
Lithium
Collections
Delegates
Enums
Interfaces
IO
Lithium.csproj.vspscc
LithiumControl.bmp
Shapes
UI
Visitors
ModelConverter
App.ico
ModelConverter.csproj.vspscc
ParseTree
App.ico
ParseTree.csproj.vspscc
ToolsExample
App.ico
ToolsExample.csproj.vspscc
OpenNLP
OpenNLP.csproj.vspscc
SharpEntropy.dll
Tools
Chunker
NameFind
Parser
PosTagger
SentenceDetect
Tokenize
Util
englishparsing_src.zip
Lithium.csproj.user
LithiumControl.bmp
App.ico
ModelConverter.csproj.user
OpenNLP.csproj.user
SharpEntropy.dll
vssver.scc
vssver.scc
vssver.scc
vssver.scc
vssver.scc
vssver.scc
vssver.scc
App.ico
ParseTree.csproj.user
App.ico
ToolsExample.csproj.user
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Netron.Lithium
{
	/// <summary>
	/// Represents the connection between two connectors
	/// </summary>
	public class Connection : Entity
	{

		#region Fields
		/// <summary>
		/// the shape where the connection starts
		/// </summary>
		protected ShapeBase from;
		/// <summary>
		/// the shape where the connection ends
		/// </summary>
		protected ShapeBase to;
		/// <summary>
		/// the start and end points
		/// </summary>
		protected Point start, end;
		/// <summary>
		/// the pen used to draw the connection,
		/// can switch depending on the hovering state e.g.
		/// </summary>
		protected Pen currentPen;

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets the shape where the connection starts
		/// </summary>
		public ShapeBase From
		{
			get{return from;}
			set{from = value;}
		}

		/// <summary>
		/// Gets or sets where the connection ends
		/// </summary>
		public ShapeBase To
		{
			get{return to;}
			set{to = value;}
		}

		/// <summary>
		/// Get the point where the connection starts
		/// </summary>
		public Point Start
		{
			get
			{
				
				
				return new Point(from.X+from.Width/2,from.Y+from.Height/2);	
			}
		}

		/// <summary>
		/// Gets the point where connection ends
		/// </summary>
		public Point End
		{
			get
			{
				end = new Point(to.X+to.Width/2,to.Y+to.Height/2);
				
				return end;
			}
		}

		#endregion

		#region Constructors
		/// <summary>
		/// Default ctor
		/// </summary>
		public Connection()
		{
			
		}
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="from">the shape where the connection starts</param>
		/// <param name="to">the shape where the connection ends</param>
		public Connection(ShapeBase from, ShapeBase to)
		{
			this.from = from;			
			this.to = to;
			currentPen = blackPen;
			
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="from">the shape where the connection starts</param>
		/// <param name="to">the shape where the connection ends</param>
		/// <param name="color">the color of the connection</param>
		public Connection(ShapeBase from, ShapeBase to, Color color) : this(from, to)
		{
			currentPen = new Pen(color, 1f);
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="from">the shape where the connection starts</param>
		/// <param name="to">the shape where the connection ends</param>
		/// <param name="color">the color of the connection</param>
		/// <param name="width">the (float) width of the connection (in pixels)</param>
		public Connection(ShapeBase from, ShapeBase to, Color color, float width) : this(from, to, color)
		{
			currentPen = new Pen(color, width);
		}
		#endregion

		#region Methods

		/// <summary>
		/// Paints the connection on the canvas
		/// The From part is always the child node while the To part is 
		/// always the parent node.
		/// Hence; 
		/// - vertical: Parent->Child <=> Top->Bottom
		/// - horizontal: Parent->Child <=> Left->Right
		/// </summary>
		/// <param name="g"></param>
		public override void Paint(System.Drawing.Graphics g)
		{
			g.SmoothingMode = SmoothingMode.AntiAlias;
			PointF p1, p2, p3, p4; //intermediate points
			if(visible)
			{
				if(hovered || isSelected)
					pen = redPen;
				else
					pen = currentPen;

				switch(site.ConnectionType)
				{
					case ConnectionType.Default:
					switch(site.LayoutDirection)
					{
						case TreeDirection.Vertical:
							p1 = new PointF(from.Left + from.Width/2, from.Top); 
							p2 = new PointF(to.Left + to.Width/2, to.Bottom+5);
							g.DrawLine(pen,p1,p2);
							break;
						case TreeDirection.Horizontal:
							p1 = new PointF(from.Left, from.Top +  from.Height/2); 
							p2 = new PointF(to.Right +4, to.Top + to.Height/2);
							g.DrawLine(pen,p1,p2);
							break;
					}
						break;
					case ConnectionType.Traditional:
					switch(site.LayoutDirection)
					{
						case TreeDirection.Vertical:
							p1 = new PointF(from.Left + from.Width/2, from.Top - (from.Top - to.Bottom)/2); 
							p2 = new PointF(to.Left + to.Width/2, from.Top - (from.Top - to.Bottom)/2);
							g.DrawLine(pen, Start,p1);
							g.DrawLine(pen, p1, p2);
							g.DrawLine(pen, End, p2);
							break;
						case TreeDirection.Horizontal:

							p1 = new PointF(to.Right + (from.Left - to.Right)/2, from.Top + from.Height/2); 
							p2 = new PointF(to.Right + (from.Left - to.Right)/2, to.Top + to.Height/2);
							g.DrawLine(pen, Start,p1);
							g.DrawLine(pen, p1, p2);
							g.DrawLine(pen, End, p2);
							break;
					}
						break;
					
					case ConnectionType.Bezier:
					switch(site.LayoutDirection)
					{
						case TreeDirection.Vertical:
							p1 = new PointF(from.Left+from.Width/2,from.Top);
							p2 = new PointF(from.Left + from.Width/2, from.Top - (from.Top - to.Bottom)/2); 
							p3 = new PointF(to.Left + to.Width/2, from.Top - (from.Top - to.Bottom)/2);
							p4 = new PointF(to.Left+to.Width/2,to.Bottom);
							g.DrawBezier(pen, p1, p2, p3, p4);
							
							break;
						case TreeDirection.Horizontal:

							p1 = new PointF(to.Right, to.Top + to.Height/2); 							
							p2 = new PointF(to.Right + (from.Left - to.Right)/2, to.Top + to.Height/2);
							p3 = new PointF(to.Right + (from.Left - to.Right)/2, from.Top + from.Height/2); 
							p4 = new PointF(from.Left,from.Top + from.Height/2);
							g.DrawBezier(pen, p1, p2, p3, p4);
							break;
					}
						break;
				}
			}
			
		}
		/// <summary>
		/// Invalidates the connection
		/// </summary>
		public override void Invalidate()
		{
			
			site.Invalidate(Rectangle.Union(from.rectangle,to.rectangle));
		}

		/// <summary>
		/// Tests if the mouse hits this connection
		/// </summary>
		/// <param name="p"></param>
		/// <returns></returns>
		public override bool Hit(Point p)
		{
			PointF p1,p2, p3, s;
			RectangleF r1, r2, r3;

			switch(site.ConnectionType)
			{
				case ConnectionType.Default:
					#region The default Hit method
					
					float o,u;
					p1 = start; p2 = end;
	
					// p1 must be the leftmost point.
					if (p1.X > p2.X) { s = p2; p2 = p1; p1 = s; }

					//this is specifically necessary when the layout works horizontally
					//the method beneth will not return true as should be in this case
					if(p1.Y==p2.Y)
					{
						p1.Y+=-3;
						return new RectangleF(p1,new SizeF(p2.X-p1.X,6)).Contains(p);
					}
					r1 = new RectangleF(p1.X, p1.Y, 0, 0);
					r2 = new RectangleF(p2.X, p2.Y, 0, 0);
					r1.Inflate(3, 3);
					r2.Inflate(3, 3);
					//this is like a topological neighborhood
					//the connection is shifted left and right
					//and the point under consideration has to be in between.						
					if (RectangleF.Union(r1, r2).Contains(p))
					{
				
						if (p1.Y < p2.Y) //SWNE
						{
							o = r1.Left + (((r2.Left - r1.Left) * (p.Y - r1.Bottom)) / (r2.Bottom - r1.Bottom));
							u = r1.Right + (((r2.Right - r1.Right) * (p.Y - r1.Top)) / (r2.Top - r1.Top));
							return ((p.X > o) && (p.X < u));
						}
						else //NWSE
						{
							o = r1.Left + (((r2.Left - r1.Left) * (p.Y - r1.Top)) / (r2.Top - r1.Top));
							u = r1.Right + (((r2.Right - r1.Right) * (p.Y - r1.Bottom)) / (r2.Bottom - r1.Bottom));
							return ((p.X > o) && (p.X < u));
						}
					}
					#endregion
					break;
				case ConnectionType.Traditional:
					#region The rectangular Hit method
						switch(site.LayoutDirection)
						{
							case TreeDirection.Vertical:
								p1 = new PointF(from.Left + from.Width/2-5, from.Top - (from.Top - to.Bottom)/2-5); //shift 5 to contain the connection
								p2 = new PointF(to.Left + to.Width/2-5, from.Top - (from.Top - to.Bottom)/2-5);
								p3 = new Point(to.Left+to.Width/2-5,to.Bottom-5);

								r1 = new RectangleF(p1, new SizeF(10,(from.Top - to.Bottom)/2+5)); 
								if(p1.X<p2.X)
									r2 = new RectangleF(p1,new SizeF(p2.X-p1.X,10));
								else
									r2 = new RectangleF(p2,new SizeF(p1.X-p2.X,10));
								r3 = new RectangleF(p3, new SizeF(10, (from.Top - to.Bottom)/2+5));
								return r1.Contains(p.X,p.Y) || r2.Contains(p.X,p.Y) || r3.Contains(p.X,p.Y) ;
								
							case TreeDirection.Horizontal:

								p1 = new PointF(to.Right + (from.Left - to.Right)/2, from.Top + from.Height/2); 
								p2 = new PointF(to.Right + (from.Left - to.Right)/2, to.Top + to.Height/2);
							
								break;
						}
					#endregion
					break;
			}


			return false;
		}

		/// <summary>
		/// Moves the connection with the given shift
		/// </summary>
		/// <param name="p"></param>
		public override void Move(Point p)
		{

		}


		#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

Share

About the Author

Richard Northedge
Web Developer
United Kingdom United Kingdom
Richard Northedge is a senior developer with a UK Microsoft Gold Partner company. He has a postgraduate degree in English Literature, has been programming professionally since 1998 and has been an MCSD since 2000.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141030.1 | Last Updated 13 Dec 2006
Article Copyright 2005 by Richard Northedge
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid