Пример #1
0
		public ArrowUtils( ArrowStyle pstyle,  PointCollection pPoints )
		{
			points = pPoints.Clone();
			style = pstyle;
			//
			// TODO: Add constructor logic here
			//
		}
Пример #2
0
		public static PointF GetBezierPt(PointCollection points, int segment, float t)
		{
			float x0 = points[segment * 3 + 0].X;
			float y0 = points[segment * 3 + 0].Y;
			float x1 = points[segment * 3 + 1].X;
			float y1 = points[segment * 3 + 1].Y;
			float x2 = points[segment * 3 + 2].X;
			float y2 = points[segment * 3 + 2].Y;
			float x3 = points[segment * 3 + 3].X;
			float y3 = points[segment * 3 + 3].Y;

			float tt = t;

			float q0 = (1-tt)*(1-tt)*(1-tt);
			float q1 = 3*tt*(1-tt)*(1-tt);
			float q2 = 3*tt*tt*(1-tt);
			float q3 = tt*tt*tt;
			float xt = q0*x0 + q1*x1 + q2*x2 + q3*x3;
			float yt = q0*y0 + q1*y1 + q2*y2 + q3*y3;

			return new PointF(xt, yt);
		}
Пример #3
0
        internal void onArrowSplit(bool added, int idx, int cnt)
        {
            if (added)
            {
                foreach (Attachment attc in attachments)
                {
                    switch (attc.type)
                    {
                    case AttachTo.ArrowPoint:
                    {
                        int point = attc.attData;
                        if (point >= idx)
                        {
                            attc.attData += cnt;
                        }
                    }
                    break;

                    case AttachTo.ArrowSegment:
                    {
                        int segment = attc.attData;
                        if (segment >= idx)
                        {
                            attc.attData += cnt;
                        }
                    }
                    break;
                    }
                }                       // for
            }
            else
            {
                foreach (Attachment attc in attachments)
                {
                    switch (attc.type)
                    {
                    case AttachTo.ArrowPoint:
                    {
                        int point = attc.attData;
                        if (point >= idx)
                        {
                            if (point < idx + cnt)
                            {
                                attc.attData = idx;
                            }
                            else
                            {
                                attc.attData -= cnt;
                            }
                        }
                    }
                    break;

                    case AttachTo.ArrowSegment:
                    {
                        int segment = attc.attData;
                        if (segment >= idx)
                        {
                            if (segment < idx + cnt)
                            {
                                attc.attData = idx - 1;
                            }
                            else
                            {
                                attc.attData -= cnt;
                            }
                            if (attc.attData < 0)
                            {
                                attc.attData = 0;
                            }
                        }
                    }
                    break;
                    }
                }                       // for
            }

            prevPoints = ((Arrow)mainObj).Points.Clone();
        }
Пример #4
0
		/// <summary>
		/// Gets rectangle of the arrow text
		/// </summary>
		/// <param name="g">GraphicsPath</param>
		/// <param name="style">Style of the arrow</param>
		/// <param name="textStyle">Style of the arrow text</param>
		/// <param name="points">Arrow's point collection</param>
		/// <param name="textColor">Text color</param>
		/// <param name="segmentCount">Arrow segments count</param>
		/// <param name="text">Arrow's text itself</param>
		/// <param name="textFont">Arrow's text font</param>
		/// <param name="rect">Bounding rect</param>
		/// <param name="a">Text's rotation angle to be returned</param>
		/// <returns>Arrow text's rectangle</returns>
		private RectangleF getTextRect(Graphics g , ArrowStyle style, ArrowTextStyle textStyle, PointCollection points , Color textColor ,int segmentCount , 
			string text , Font textFont , RectangleF rect , ref float a )
		{
			// DrawString crashes with a too small PageScale
			if (g.PageScale < 0.01) return RectangleF.Empty;

			System.Drawing.Brush brText = new System.Drawing.SolidBrush(textColor);
			StringFormat sf = StringFormat.GenericDefault;
			sf.Alignment = StringAlignment.Center;
			sf.LineAlignment = StringAlignment.Far;

			float x =0 , y = 0;

			a  = 0;
			ArrowUtils au = new ArrowUtils(style,points );
			System.Drawing.SizeF textSize = g.MeasureString(text, textFont);

			if (textStyle == ArrowTextStyle.Rotate)
			{
				// Find the segment near which the text will be drawn
				int pt = points.Count / 2 - 1;
				int jump = 1;
				int ptBest = pt;
				float r = 0,  rBest = 0;
				if (style != ArrowStyle.Bezier)
				{
					if (style == ArrowStyle.Cascading ||
						(style == ArrowStyle.Polyline && segmentCount % 2 == 1))
					{
						do
						{
							MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
								points[pt], points[pt + 1], ref a, ref r);
							if (r > rBest)
							{
								rBest = r;
								ptBest = pt;
							}
							pt = pt + jump;
							jump = -Math.Sign(jump) * (Math.Abs(jump) + 1);
							if(pt < 0 || pt >= points.Count - 1)
								break;
						}
						while(textSize.Width > r);
						pt = ptBest;
						x = (points[pt].X + points[pt + 1].X) / 2;
						y = (points[pt].Y + points[pt + 1].Y) / 2;
					}
					else
					{
						pt = pt + 1;
						x = points[pt].X;
						y = points[pt].Y;
					}
				}
				else
				{
					if(segmentCount % 2 == 1)
					{
						pt = (pt + 1) / 4;
						PointF ptMid = ArrowUtils.GetBezierPt(points, pt, 0.5f);
						x = ptMid.X;
						y = ptMid.Y;
					}
					else
					{
						pt = (pt + 1) / 4;
						PointF ptMid = points[(pt + 1) * 3];
						x = ptMid.X;
						y = ptMid.Y;
					}
				}

						
				// Find out the angle
				if (style != ArrowStyle.Bezier)
				{
					if( style == ArrowStyle.Cascading ||
						(style == ArrowStyle.Polyline && segmentCount % 2 == 1))
					{
						PointF pt1 = points[pt];
						PointF pt2 = points[pt + 1];
						MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
							pt1, pt2, ref a, ref r);
					}
					else
					{
						float r1 = 0, a1 = 0;
						MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
							points[pt - 1], points[pt], ref a, ref r);
						MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
							points[pt], points[pt + 1], ref a1, ref r1);
						a = (a + a1) / 2;
					}
				}
				else
				{
					if (segmentCount % 2 == 1)
					{
						PointF pt1 = ArrowUtils.GetBezierPt(points, pt, 0.45f);
						PointF pt2 = ArrowUtils.GetBezierPt(points, pt, 0.55f);
						MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
							pt1, pt2, ref a, ref r);
					}
					else
					{
						PointF pt1 = ArrowUtils.GetBezierPt(points, pt, 0.95f);
						PointF pt2 = ArrowUtils.GetBezierPt(points, pt + 1, 0.05f);
						MindFusion.Geometry.Geometry2D.Convert.DekartToPolar(
							pt1, pt2, ref a, ref r);
					}
				}

				a = 180 - a;
				if (a > 90 && a < 270)
					a -= 180;
					
			
			}
			else if (textStyle == ArrowTextStyle.Center)
			{
				if(points.Count % 2 == 1)
				{
					x = points[points.Count / 2].X;
					y = points[points.Count / 2].Y;
				}
				else
				{
					x = points[points.Count / 2 - 1].X + points[points.Count / 2].X;
					y = points[points.Count / 2 - 1].Y + points[points.Count / 2].Y;
					x /= 2;
					y /= 2;
				}

				//g.DrawString(text, textFont, brText, new PointF(x, y), sf);
			}
			else if (textStyle == ArrowTextStyle.OverLongestSegment)
			{
				
				// find the center point of longest segment
				int longest = au.getLongestSegment();
				PointF center = au.getSegmentCenter(longest);

				// see how much space the text requires
				StringFormat cf = m_FlowChart.TextFormat;
				SizeF size = g.MeasureString(text, textFont);
				size.Width += ArrowUtils.getMillimeter(m_FlowChart.MeasureUnit);
				size.Height += ArrowUtils.getMillimeter(m_FlowChart.MeasureUnit);

				
			
			}

			brText.Dispose();

			RectangleF rc = new RectangleF(x - textSize.Width/2 ,y - textSize.Height/2,textSize.Width, textSize.Height);
			return rc;

		}
Пример #5
0
		public void Read(System.Xml.XmlReader reader)
		{
			// Disable auto-routing for a while
			_diagram.DontRouteForAwhile = true;

			_diagram.ClearAll();

			// Read while <Diagram> reached
			while (reader.Read())
				if (reader.Name == "Diagram")
					break;

			if (reader.Name != "Diagram")
				throw new InvalidFormatException("Invalid FlowChart document");

			// Check version
			_version = 1;
			if (reader.HasAttributes)
				_version = XmlConvert.ToInt32(reader.GetAttribute("Version"));

			// Read the brushes
			SortedList brushes = new SortedList();
			Brush brush;
			int count;
			int i;
			int id = 0;
			string type;
			int d;

			ReadMandatory(reader, "Brushes",
				"Brushes element missing or invalid");
			count = XmlConvert.ToInt32(
				reader.GetAttribute("Count"));
			for(i = 0; i < count; i++)
			{
				ReadMandatory(reader, "Brush",
					"Unrecognized brush token");

				id = XmlConvert.ToInt32(
					reader.GetAttribute("Id"));
				type = reader.GetAttribute("Type");

				brush = null;

				switch(type)
				{
					case "Solid":
					{
						d = reader.Depth;
						string name;
						while(true)
						{
							// Read element
							reader.Read();
							if(reader.Depth == d)
								break;

							name = reader.Name;
							// Read the value
							reader.Read();

							if(name == "Color")
							{
								Color c = XmlConvert.ToColor(reader.Value);
								brush = new FlowChartX.SolidBrush(c);
							}

							// Read the closing element
							reader.Read();
						}
					}
						break;
					case "Gradient":
					{
						d = reader.Depth;
						float angle = 0;
						Blend blend = null;
						Color c1 = Color.Black, c2 = Color.White;
						ColorBlend cblend = null;
						while(true)
						{
							// Read element
							reader.Read();
							if(reader.Depth == d)
								break;

							switch (reader.Name)
							{
								case "Angle":
									// Read the value
									reader.Read();
									angle = XmlConvert.ToSingle(reader.Value);
									break;
								case "Blend":
								{
									// Read positions
									reader.Read();
									float[] pos = ReadFloatArrayElement(reader);
									// Read factors
									reader.Read();
									float[] fac = ReadFloatArrayElement(reader);

									if(pos.Length != fac.Length)
										throw new InvalidFormatException(
											"Factors and positions in a gradient brush " +
											"have different lengths");

									blend = new Blend();
									blend.Positions = pos;
									blend.Factors = fac;
								}
									break;
								case "Color1":
									// Read the value
									reader.Read();
									c1 = XmlConvert.ToColor(reader.Value);
									break;
								case "Color2":
									// Read the value
									reader.Read();
									c2 = XmlConvert.ToColor(reader.Value);
									break;
								case "ColorBlend":
								{
									// Read positions
									reader.Read();
									float[] pos = ReadFloatArrayElement(reader);
									// Read colors
									reader.Read();
									Color[] colors = ReadColorArrayElement(reader);

									cblend = new ColorBlend();
									cblend.Positions = pos;
									cblend.Colors = colors;
								}
									break;
							}

							// Read the closing element
							reader.Read();
						}

						brush = new FlowChartX.LinearGradientBrush(c1, c2);
						((LinearGradientBrush)brush).Angle = angle;
						((LinearGradientBrush)brush).Blend = blend;
						((LinearGradientBrush)brush).InterpolationColor = cblend;
					}
						break;
					case "Texture":
					{
						d = reader.Depth;
						string name;
						WrapMode wm = WrapMode.Tile;
						Image img = null;
						while(true)
						{
							// Read element
							reader.Read();
							if(reader.Depth == d)
								break;

							name = reader.Name;
							// Read the value
							reader.Read();

							switch(name)
							{
								case "WrapMode":
									wm = (WrapMode)XmlConvert.ToEnum(
										typeof(WrapMode), reader.Value);
									break;
								case "Image":
									img = _version >= 4 ? XmlConvert.ToImageV4(reader.Value) :
										XmlConvert.ToImage(reader.Value);
									break;
							}

							// Read the closing element
							reader.Read();

							if (img != null)
								brush = new FlowChartX.TextureBrush(img, wm);
						}
					}
						break;
					case "Hatch":
					{
						d = reader.Depth;
						string name;
						Color fore = Color.Black, back = Color.White;
						HatchStyle style = HatchStyle.ForwardDiagonal;
						while(true)
						{
							// Read element
							reader.Read();
							if(reader.Depth == d)
								break;

							name = reader.Name;
							// Read the value
							reader.Read();

							switch(name)
							{
								case "ForeColor":
									fore = XmlConvert.ToColor(reader.Value);
									break;
								case "BackColor":
									back = XmlConvert.ToColor(reader.Value);
									break;
								case "Style":
									style = (HatchStyle)XmlConvert.ToEnum(
										typeof(HatchStyle), reader.Value);
									break;
							}

							// Read the closing element
							reader.Read();

							brush = new FlowChartX.HatchBrush(
								style, fore, back);
						}
					}
						break;
				}

				if(!brushes.Contains(id) && brush != null)
					brushes.Add(id, brush);
			}

			// Read the brushes closing element
			if(count > 0)
				reader.Read();

			ReadMandatory(reader, "Environment",
				"Environment element missing or invalid");

			// Read all appearance properties
			ReadMandatory(reader, "Appearance",
				"Appearance element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Appearance section");

			// Read all bahaviour properties
			ReadMandatory(reader, "Behaviour",
				"Behaviour element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Behaviour section");

			// Read all default properties
			ReadMandatory(reader, "Defaults",
				"Defaults element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Defaults section");

			// Read default brushes and pens
			ReadMandatory(reader, "DefaultsGDI",
				"DefaultsGDI element missing or invalid");
			d = reader.Depth;
			while(true)
			{
				// Read starting tag
				reader.Read();
				if(reader.Depth == d)
					break;

				switch (reader.Name)
				{

					case "BoxBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						_diagram.BoxBrush = (FlowChartX.Brush)brushes[id];
						break;

					case "TableBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						_diagram.TableBrush = (FlowChartX.Brush)brushes[id];
						break;
/*
					case "TableCaptionBackBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						_diagram.TableCaptionBackBrush = (FlowChartX.Brush)brushes[id];
						break;
*/
					case "ArrowBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						_diagram.ArrowBrush = (FlowChartX.Brush)brushes[id];
						break;

					case "BackBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						_diagram.BackBrush = (FlowChartX.Brush)brushes[id];
						break;

					case "ExteriorBrush":
						id = XmlConvert.ToInt32(
							reader.GetAttribute("Id"));
						if (id == -1)
							_diagram.ExteriorBrush = null;
						else
							_diagram.ExteriorBrush = (FlowChartX.Brush)brushes[id];
						break;

					case "BoxPen":
						_diagram.BoxPen.Brush = null; // force release
						_diagram.BoxPen = (FlowChartX.Pen)
							ReadPenElement(reader, brushes);
						break;

					case "TablePen":
						_diagram.TablePen.Brush = null; // force release
						_diagram.TablePen = (FlowChartX.Pen)
							ReadPenElement(reader, brushes);
						break;

					case "ArrowPen":
						_diagram.ArrowPen.Brush = null; // force release
						_diagram.ArrowPen = (FlowChartX.Pen)
							ReadPenElement(reader, brushes);
						break;

				}
			}

			// Read all grid properties
			ReadMandatory(reader, "Grid",
				"Grid element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Grid section");

			// Read all layout properties
			ReadMandatory(reader, "Layout",
				"Layout element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Layout section");

			// Read all miscellaneous properties
			ReadMandatory(reader, "Miscellaneous",
				"Miscellaneous element missing or invalid");
			if(!ReadProperties(reader, _diagram, reader.Depth + 1))
				throw new InvalidFormatException("Unexpected " +
					"EOF in the Miscellaneous section");

			// Read the Environment closing element
			reader.Read();


			// Proceed to diagram objects //
			Box b;
			ControlHost h;
			Arrow a;
			Table t;
			Group g;
			object from, to;
			PointCollection points = new PointCollection(0);
			int idFrom, idTo, idArrow;
			int rowFrom, rowTo;
			int row, col;
			SortedList objects = new SortedList();
			SortedList zOrder = new SortedList();
			SortedList controlZOrder = new SortedList();
			int zIndex;
			id = 0;

			// Read boxes info
			ReadMandatory(reader, "Boxes",
				"Boxes element missing or invalid");
			count = XmlConvert.ToInt32(reader.GetAttribute("Count"));
			int brushId = -1;
			FlowChartX.Pen pen = null;
			FlowChartX.Pen headPen = null;
			for(i = 0; i < count; i++)
			{
				// Read the starting element
				ReadMandatory(reader, "Box",
					"Unrecognized box token");

				id = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				zIndex = XmlConvert.ToInt32(reader.GetAttribute("ZIndex"));
				b = _diagram.CreateBox(0, 0, 1, 1);
				objects.Add(id, b);
				zOrder.Add(zIndex, b);

				// Read the shape
				string shape;
				reader.Read();
				if(!reader.IsEmptyElement)
				{
					reader.Read();
					shape = reader.Value;
					reader.Read();
				}
				else
				{
					shape = "Rectangle";
				}

				BoxStyle style = BoxStyle.Rectangle;
				switch(shape)
				{
					case "RoundRectangle":
						style = BoxStyle.RoundedRectangle;
						break;
					default:
						// Assume it is a complex shape
						style = BoxStyle.Shape;
						break;
				}
				b.Style = style;
				if(style == BoxStyle.Shape)
					b.Shape = ShapeTemplate.FromId(shape);

				// Read brush
				reader.Read();
				if (reader.GetAttribute("Id") != null)
					brushId = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				else
					brushId = -1;
				// Read the pen
				reader.Read();
				pen = ReadPenElement(reader, brushes);

				if(!ReadProperties(reader, b, reader.Depth))
					throw new InvalidFormatException(
						"Unexpected EOF while parsing box info. Box: " +
						i.ToString());

				// Set brush and pen
				if(brushId != -1)
					b.Brush = (FlowChartX.Brush)brushes[brushId];
				if(pen != null)
					b.Pen = pen;
			}

			// Read boxes closing element
			if(count > 0)
				reader.Read();

			// Read control hosts
			if (_version >= 3)
			{
				string assemblyName;
				string typeName;
				ReadMandatory(reader, "ControlHosts",
					"ControlHosts element missing or invalid");
				count = XmlConvert.ToInt32(reader.GetAttribute("Count"));

				for (i = 0; i < count; i++)
				{
					// Read the host element
					ReadMandatory(reader, "Host",
						"Host element missing or invalid");

					id = XmlConvert.ToInt32(reader.GetAttribute("Id"));
					zIndex = XmlConvert.ToInt32(reader.GetAttribute("ZIndex"));
					assemblyName = reader.GetAttribute("ControlAssembly");
					typeName = reader.GetAttribute("ControlType");
					int controlZIndex = XmlConvert.ToInt32(reader.GetAttribute("ControlZIndex"));

					// Create the control host and add it to the diagram
					h = _diagram.CreateControlHost(0, 0, 1, 1);
					objects.Add(id, h);
					zOrder.Add(zIndex, h);
					controlZOrder.Add(controlZIndex, h.Control);

					// Read brush
					reader.Read();
					if(reader.GetAttribute("Id") != null)
						brushId = XmlConvert.ToInt32(reader.GetAttribute("Id"));
					else
						brushId = -1;
					// Read the pen
					reader.Read();
					pen = ReadPenElement(reader, brushes);

					if (typeName != "" && assemblyName != "")
					{
						System.Type controlType = Utilities.getLoadedType(typeName, assemblyName);
						if (controlType == null)
							throw new FileLoadException("Cannot load hosted control of type " + typeName);
						ConstructorInfo ctorInfo = controlType.GetConstructor(System.Type.EmptyTypes);
						// Instantiate
						h.Control = (System.Windows.Forms.Control)ctorInfo.Invoke(null);

						// Read control properties
						BinaryFormatter fmt = new BinaryFormatter();
						fmt.Binder = new DeserializationHack();
						ReadControlProperties(reader, h.Control, fmt);
					}
					else
					{
						h.Control = null;
					}

					// Read properties
					if (!ReadProperties(reader, h, reader.Depth))
						throw new InvalidFormatException(
							"Unexpected EOF while parsing control host info. ControlHost: " +
							i.ToString());

					// Set brush and pen
					if (brushId != -1)
						h.Brush = (FlowChartX.Brush)brushes[brushId];
					if (pen != null)
						h.Pen = pen;
				}

				// Update the z-indices of the contained controls
				foreach (System.Windows.Forms.Control control in controlZOrder.Values)
					control.BringToFront();

				// Read control hosts closing element
				if(count > 0)
					reader.Read();
			}

			// Read tables info
			ReadMandatory(reader, "Tables",
				"Tables element missing or invalid");
			count = XmlConvert.ToInt32(reader.GetAttribute("Count"));
			for(i = 0; i < count; i++)
			{
				// Read the table element
				ReadMandatory(reader, "Table",
					"Unrecognized table token");

				id = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				zIndex = XmlConvert.ToInt32(reader.GetAttribute("ZIndex"));
				t = _diagram.CreateTable(0, 0, 1, 1);
				objects.Add(id, t);
				zOrder.Add(zIndex, t);

				t.RowCount = XmlConvert.ToInt32(reader.GetAttribute("Rows"));
				t.ColumnCount = XmlConvert.ToInt32(reader.GetAttribute("Columns"));

				// Read cell data
				ReadMandatory(reader, "Data",
					"Data element missing or invalid");
				d = reader.Depth;
				row = 0;
				col = 0;
				if(!reader.IsEmptyElement)
				{
					while(true)
					{
						reader.Read();
						if(d == reader.Depth)
							break;

						// Read brush in V5
						if (_version >= 5)
						{
							reader.Read();
							int bid = -1;
							if (reader.GetAttribute("Id") != null)
								bid = XmlConvert.ToInt32(reader.GetAttribute("Id"));
							if (bid != -1)
								t[col, row].Brush = (FlowChartX.Brush)brushes[bid];
							else
								t[col, row].Brush = null;

							ReadProperties(reader, t[col, row], reader.Depth);
						}
						else
						{
							ReadProperties(reader, t[col, row], reader.Depth + 1);
						}

						col++;
						if(col >= t.ColumnCount)
						{
							col = 0;
							row++;
						}
					}
				}

				// Read row data
				ReadMandatory(reader, "Rows",
					"Rows element missing or invalid");
				d = reader.Depth;
				row = 0;
				if(!reader.IsEmptyElement)
				{
					while(true)
					{
						reader.Read();
						if(d == reader.Depth)
							break;

						ReadProperties(reader, t.Rows[row], reader.Depth + 1);
						row++;
					}
				}

				// Read column data
				ReadMandatory(reader, "Columns",
					"Columns element missing or invalid");
				d = reader.Depth;
				col = 0;
				if(!reader.IsEmptyElement)
				{
					while(true)
					{
						reader.Read();
						if(d == reader.Depth)
							break;

						ReadProperties(reader, t.Columns[col], reader.Depth + 1);
						col++;
					}
				}

				// Read brush
				reader.Read();
				if (reader.GetAttribute("Id") != null)
					brushId = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				else
					brushId = -1;

				// Read the caption brush
				int captionBrushId = -1;
				if (_version >= 10)
				{
					reader.Read();
					if (reader.GetAttribute("Id") != null)
						captionBrushId = XmlConvert.ToInt32(reader.GetAttribute("Id"));
					else
						captionBrushId = -1;
				}

				// Read the pen
				reader.Read();
				pen = ReadPenElement(reader, brushes);

				// Read table properties
				if(!ReadProperties(reader, t, reader.Depth))
					throw new InvalidFormatException(
						"Unexpected EOF while parsing table info. Table: " +
						i.ToString());

				// Set brush and pen
				if (brushId != -1)
					t.Brush = (FlowChartX.Brush)brushes[brushId];
				if (captionBrushId != -1)
					t.CaptionBackBrush = (FlowChartX.Brush)brushes[captionBrushId];
				if (pen != null)
					t.Pen = pen;
			}

			// Read tables closing element
			if(count > 0)
				reader.Read();

			if (_version >= 7)
			{
				ReadMandatory(reader, "Containers",
					"Containers element missing or invalid");

				int ccount = XmlConvert.ToInt32(reader.GetAttribute("Count"));

				if (ccount > 0)
				{
					int cdepth = reader.Depth;
					while (true)
					{
						reader.Read();
						if (reader.Depth == cdepth)
							break;
					}
				}
			}

			// Read arrows info
			ReadMandatory(reader, "Arrows",
				"Arrows element missing or invalid");
			count = XmlConvert.ToInt32(reader.GetAttribute("Count"));
			for(i = 0; i < count; i++)
			{
				// Read the arrow element
				ReadMandatory(reader, "Arrow",
					"Unrecognized arrow token");

				// Read the origin and destination indices
				idFrom = XmlConvert.ToInt32(reader.GetAttribute("From"));
				idTo = XmlConvert.ToInt32(reader.GetAttribute("To"));
				idArrow = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				zIndex = XmlConvert.ToInt32(reader.GetAttribute("ZIndex"));

				try
				{
					rowFrom = XmlConvert.ToInt32(reader.GetAttribute("RowFrom"));
				}
				catch
				{
					rowFrom = -1;
				}
				try
				{
					rowTo = XmlConvert.ToInt32(reader.GetAttribute("RowTo"));
				}
				catch
				{
					rowTo = -1;
				}

				if (idTo == -1 || idFrom == -1)
				{
					if (idTo == -1 && idFrom != -1)
					{
						from = objects[idFrom];

						Node nodeFrom = from as Node;

						// Temporarily turn allow arrows off
						bool allowIn = nodeFrom.AllowIncomingArrows;
						bool allowOut = nodeFrom.AllowOutgoingArrows;

						nodeFrom.AllowIncomingArrows = true;
						nodeFrom.AllowOutgoingArrows = true;

						a = _diagram.CreateArrow(nodeFrom, PointF.Empty);

						nodeFrom.AllowIncomingArrows = allowIn;
						nodeFrom.AllowOutgoingArrows = allowOut;
					}
					else if (idTo != -1 && idFrom == -1)
					{
						to = objects[idTo];

						Node nodeTo = to as Node;

						// Temporarily turn allow arrows off
						bool allowIn = nodeTo.AllowIncomingArrows;
						bool allowOut = nodeTo.AllowOutgoingArrows;

						nodeTo.AllowIncomingArrows = true;
						nodeTo.AllowOutgoingArrows = true;

						a = _diagram.CreateArrow(PointF.Empty, (Node)to);

						nodeTo.AllowIncomingArrows = allowIn;
						nodeTo.AllowOutgoingArrows = allowOut;
					}
					else
					{
						a = _diagram.CreateArrow(PointF.Empty, PointF.Empty);
					}
				}
				else
				{
					from = objects[idFrom];
					to = objects[idTo];

					Node nodeFrom = from as Node;
					Node nodeTo = to as Node;

					// Temporarily turn allow arrows off
					bool fromAllowIn = nodeFrom.AllowIncomingArrows;
					bool fromAllowOut = nodeFrom.AllowOutgoingArrows;
					bool toAllowIn = nodeTo.AllowIncomingArrows;
					bool toAllowOut = nodeTo.AllowOutgoingArrows;

					nodeFrom.AllowIncomingArrows = true;
					nodeFrom.AllowOutgoingArrows = true;
					nodeTo.AllowIncomingArrows = true;
					nodeTo.AllowOutgoingArrows = true;

					if(rowFrom == -1 && rowTo == -1)
					{
						a = _diagram.CreateArrow((Node)from, (Node)to);
					}
					else if(rowFrom != -1 && rowTo == -1)
					{
						a = _diagram.CreateArrow((Table)from, rowFrom, (Node)to);
					}
					else if(rowFrom == -1 && rowTo != -1)
					{
						a = _diagram.CreateArrow((Node)from, (Table)to, rowTo);
					}
					else
					{
						a = _diagram.CreateArrow((Table)from, rowFrom,
							(Table)to, rowTo);
					}

					nodeFrom.AllowIncomingArrows = fromAllowIn;
					nodeFrom.AllowOutgoingArrows = fromAllowOut;
					nodeTo.AllowIncomingArrows = toAllowIn;
					nodeTo.AllowOutgoingArrows = toAllowOut;
				}

				// Read the control points
				ReadMandatory(reader, "Data",
					"Data element missing or invalid");
				d = reader.Depth;
				float x, y;
				points.Clear();
				while(true)
				{
					// Read the point
					reader.Read();

					if(reader.Depth == d)
						break;

					x = XmlConvert.ToSingle(reader.GetAttribute("X"));
					y = XmlConvert.ToSingle(reader.GetAttribute("Y"));

					points.Add(new PointF(x, y));
				}

				// Read brush
				reader.Read();
				if(reader.GetAttribute("Id") != null)
					brushId = XmlConvert.ToInt32(reader.GetAttribute("Id"));
				else
					brushId = -1;
				// Read the pen
				reader.Read();
				pen = ReadPenElement(reader, brushes);
				// Read head pen
				if (_version > 1)
				{
					reader.Read();
					headPen = ReadPenElement(reader, brushes);
				}

				// Read the properties
				if(!ReadProperties(reader, a, reader.Depth))
					throw new InvalidFormatException(
						"Unexpected EOF while parsing arrow info. Arrow: " +
						i.ToString());

				// Set again segment count, because
				// if the arrow is routed, settings
				// segment count through SegmentCount property
				// won't have any effect
				if (a.Style == ArrowStyle.Bezier)
					a.InternalSegmentCount = (short)((points.Count - 1) / 3);
				else
					a.InternalSegmentCount = (short)(points.Count - 1);

				// Set the control points
				for(int p = 0; p < points.Count; p++)
					a.ControlPoints[p] = points[p];
				a.UpdateFromPoints();

				// Set brush and pen
				if(brushId != -1)
					a.Brush = (FlowChartX.Brush)brushes[brushId];
				if(pen != null)
					a.Pen = pen;
				if (headPen != null)
					a.HeadPen = headPen;

				objects.Add(idArrow, a);
				zOrder.Add(zIndex, a);
			}

			// Read arrows closing element
			if(count > 0)
				reader.Read();


			// Adjust z-order
			for(i = 0; i < zOrder.Count; i++)
			{
				ChartObject obj = (ChartObject)zOrder.GetByIndex(i);
				obj.ZIndex = (int)zOrder.GetKey(i);
			}


			// Read groups
			ReadMandatory(reader, "Groups",
				"Groups element missing or invalid");
			count = XmlConvert.ToInt32(reader.GetAttribute("Count"));
			for(i = 0; i < count; i++)
			{
				// Read the group element
				ReadMandatory(reader, "Group",
					"Unrecognized group token");

				// Read the main object
				reader.Read();
				id = XmlConvert.ToInt32(reader.GetAttribute("Id"));

				g = _diagram.CreateGroup((ChartObject)objects[id]);

				// Read group's visibility
				reader.Read();
				reader.Read();
				g.Visible = XmlConvert.ToBoolean(reader.Value.ToLower());
				reader.Read();

				// Read AutoDeleteItems flag
				if (_version >= 7)
				{
					reader.Read();
					reader.Read();
					g.AutoDeleteItems = XmlConvert.ToBoolean(reader.Value.ToLower());
					reader.Read();
				}

				// Read Expandable flag
				if (_version >= 8)
				{
					reader.Read();
					reader.Read();
					g.Expandable = XmlConvert.ToBoolean(reader.Value.ToLower());
					reader.Read();
				}

				// Read FollowMasterRotation flag
				if (_version >= 9)
				{
					reader.Read();
					reader.Read();
					g.FollowMasterRotation = XmlConvert.ToBoolean(reader.Value.ToLower());
					reader.Read();
				}

				reader.Read(); // read Tag or Attachments
				if (reader.Name == "Tag")
				{
					if (_options.CustomTagSerialization)
					{
						if(DeserializeTag != null)
						{
							SerializeTagArgs args = new SerializeTagArgs(g, null, reader);
							DeserializeTag(this, args);
						}
					}
					else
					{
						// Read the value
						reader.Read();

						if(DeserializeTag != null)
						{
							SerializeTagArgs args = new SerializeTagArgs(g);
							args.Representation = reader.Value;
							DeserializeTag(this, args);
						}
					}

					// Read the closing Tag element
					reader.Read();

					// Read the Attachments
					reader.Read();
				}

				// Process attachments
				int acount = XmlConvert.ToInt32(reader.GetAttribute("Count"));
				int ai;
				int adata;
				Node node;
				float al, at, ar, ab;
				AttachTo atype;
				for(ai = 0; ai < acount; ai++)
				{
					// Read attachment element
					reader.Read();

					// Read data
					reader.Read();
					reader.Read();
					adata = XmlConvert.ToInt32(reader.Value);
					reader.Read();

					// Read object
					reader.Read();
					reader.Read();
					node = (Node)objects[XmlConvert.ToInt32(reader.Value)];
					reader.Read();

					// Read percents
					reader.Read();
					al = XmlConvert.ToSingle(reader.GetAttribute("Left"));
					at = XmlConvert.ToSingle(reader.GetAttribute("Top"));
					ar = XmlConvert.ToSingle(reader.GetAttribute("Right"));
					ab = XmlConvert.ToSingle(reader.GetAttribute("Bottom"));

					// Read type
					reader.Read();
					reader.Read();
					atype = (AttachTo)XmlConvert.ToEnum(
						typeof(AttachTo), reader.Value);
					reader.Read();

					switch(atype)
					{
						case AttachTo.ArrowPoint:
							g.AttachToArrowPoint(node, adata);
							break;
						case AttachTo.ArrowSegment:
							g.AttachToArrowSegment(node, adata);
							break;
						case AttachTo.FixedCorner:
							g.AttachToCorner(node, adata);
							break;
						case AttachTo.Proportional:
							g.AttachProportional(node, al, at, ar, ab);
							break;
						case AttachTo.LongestHSegment:
							g.AttachToLongestHSegment(node);
							break;
						case AttachTo.SideMiddle:
							g.AttachToSideMiddle(node, adata);
							break;
					}

					// Read attachment closing element
					reader.Read();
				}

				// Read attachments' closing element
				if(acount > 0)
					reader.Read();

				// Read the group closing element
				reader.Read();
			}

			// Read groups closing element
			reader.Read();

			// Read diagram closing element
			reader.Read();

			foreach (ChartObject obj in _diagram.Objects)
				obj.onLoad();

			// Note: If exception is thrown this
			// flag will remain raised
			_diagram.DontRouteForAwhile = false;
		}
Пример #6
0
		internal void drawArrow(Graphics g, Arrow arrow, bool shadow, PointCollection points)
		{
			if (DrawArrow != null)
				DrawArrow(this, new ArrowDrawArgs(g, arrow, shadow, points));
		}
Пример #7
0
		public static PointCollection approxEllipse(RectangleF rect, int quality)
		{
			PointCollection approximation = new PointCollection(0);
			float epsilon = 1.0f / quality;

			// get the points defining the curve
			float a = rect.Width / 2;
			float b = rect.Height / 2;
			float cx = rect.X + a;
			float cy = rect.Y + b;

			for (float t = 0; t <= 3.1415f * 2; t += epsilon)
			{
				float x = (float)(cx + a * Math.Cos(t));
				float y = (float)(cy + b * Math.Sin(t));

				// draw straight line between last two calculated points
				approximation.Add(new PointF(x, y));
			}

			return approximation;
		}
Пример #8
0
		internal static float distToPolyline(PointF pt, PointCollection line_pts, int nPoints, ref int segmNum)
		{
			float nDist, nMinDist = 1000000;
			segmNum = 0;

			for (int l = 0; l < nPoints - 1; ++l)
			{
				double x1 = line_pts[l].X;
				double y1 = line_pts[l].Y;
				double x2 = line_pts[l+1].X;
				double y2 = line_pts[l+1].Y;

				double A = y1 - y2;
				double B = x2 - x1;
				double C = x1*y2 - y1*x2;

				if (Math.Abs(A) < 0.00001 && Math.Abs(B) < 0.00001)
				{
					nDist = (float)Math.Sqrt((x1-pt.X)*(x1-pt.X) + (y1-pt.Y)*(y1-pt.Y));
				}
				else
				if (Math.Abs(A) < 0.00001)
				{
					if ((pt.X > x1 && pt.X > x2) || (pt.X < x1 && pt.X < x2))
					{
						nDist = (float)Math.Min(
										Math.Sqrt((x1-pt.X)*(x1-pt.X) + (y1-pt.Y)*(y1-pt.Y)),
										Math.Sqrt((x2-pt.X)*(x2-pt.X) + (y2-pt.Y)*(y2-pt.Y)));
					}
					else
					{
						nDist = (float)Math.Abs(y1 - pt.Y);
					}
				}
				else
				{
					double xo, yo;

					yo = (A*A*pt.Y - A*B*pt.X - B*C) / (A*A + B*B);
					xo = (-C - B*yo) / A;

					if ( (xo - x1)*(xo - x2) <= 0 && (yo - y1)*(yo - y2) <= 0)
					{
						nDist = (float)Math.Sqrt((pt.X - xo)*(pt.X - xo) + (pt.Y - yo)*(pt.Y - yo));
					}
					else
					{
						nDist = (float)Math.Min(
										Math.Sqrt((x1-pt.X)*(x1-pt.X) + (y1-pt.Y)*(y1-pt.Y)),
										Math.Sqrt((x2-pt.X)*(x2-pt.X) + (y2-pt.Y)*(y2-pt.Y)));
					}
				}

				if (nMinDist > nDist)
				{
					nMinDist = nDist;
					segmNum = l;
				}
			}

			return nMinDist;
		}
Пример #9
0
		internal override void restoreState(ItemState state)
		{
			base.restoreState(state);

			ArrowState astate = (ArrowState)state;
			style = astate.style;
			segmentCount = astate.segmentCount;
			points = astate.points.Clone();
			reflexive = astate.reflexive;
			cascadeStartHorizontal = astate.cascadeStartHorizontal;

			if (orgnLink != astate.orgnLink)
			{
				orgnLink.removeArrowFromObj();
				orgnLink = astate.orgnLink;
				orgnLink.addArrowToObj();
			}
			orgnAnchor = astate.orgnAnchor;

			if (destLink != astate.destLink)
			{
				destLink.removeArrowFromObj();
				destLink = astate.destLink;
				destLink.addArrowToObj();
			}
			destAnchor = astate.destAnchor;

			updateFromPoints(false);

			if (subordinateGroup != null)
				subordinateGroup.onRestoreState();

			orgnLink.RelativePosition = astate.orgnPoint;
			destLink.RelativePosition = astate.destPoint;

			resetCrossings();
			updateText();
		}
Пример #10
0
		internal void doRoute(bool force, Link orgnLink, Link destLink, bool nowCreating)
		{
			if (!force)
				if (!autoRoute) return;

			if (flowChart.DontRouteForAwhile)
				return;

			int i;

			float gridSize = flowChart.RoutingOptions.GridSize;

			PointF startPoint = points[0];
			PointF endPoint = points[points.Count - 1];

			// get a rectangle bounding both the origin and the destination
			RectangleF bounds = orgnLink.getNodeRect(true);
			bounds = Utilities.unionRects(bounds, destLink.getNodeRect(true));
			bounds = RectangleF.Union(bounds, Utilities.normalizeRect(
				RectangleF.FromLTRB(startPoint.X, startPoint.Y, endPoint.X, endPoint.Y)));
			if (bounds.Width < gridSize * 4)
				bounds.Inflate(gridSize * 4, 0);
			if (bounds.Height < gridSize * 4)
				bounds.Inflate(0, gridSize * 4);
			bounds.Inflate(bounds.Width, bounds.Height);

			int oNearest = 0, dNearest = 0;
			routeGetEndPoints(ref startPoint, ref endPoint,
				ref oNearest, ref dNearest, orgnLink, destLink, nowCreating);

			// Get the starting and ending square
			Point ptStart = new Point((int)((startPoint.X - bounds.X) / gridSize),
				(int)((startPoint.Y - bounds.Y) / gridSize));
			Point ptEnd = new Point((int)((endPoint.X - bounds.X) / gridSize),
				(int)((endPoint.Y - bounds.Y) / gridSize));
			if (ptStart.X == ptEnd.X && ptStart.Y == ptEnd.Y)
				return;

			// init the route grid
			int gridCols = (int)(bounds.Width / gridSize);
			int gridRows = (int)(bounds.Height / gridSize);

			RoutingGrid routingGrid = flowChart.RoutingGrid;
			routingGrid.allocate(gridCols, gridRows, bounds, this);
			byte[,] grid = routingGrid.getCostGrid();
			PathNode[,] gridClosed = routingGrid.getClosedGrid();
			PathNode[,] gridOpen = routingGrid.getOpenGrid();

			bool hurry = (gridCols * gridRows > 90000) &&
				flowChart.RoutingOptions.DontOptimizeLongRoutes;
			RouteHeuristics calcRouteHeuristics = hurry ?
				RoutingOptions.DistSquare : flowChart.RoutingOptions.RouteHeuristics;

			routeFixEndRegions(grid, ref ptStart, oNearest, ref ptEnd, dNearest, gridCols, gridRows);
			grid[ptStart.X, ptStart.Y] = 0;
			grid[ptEnd.X, ptEnd.Y] = 0;

			//---------- A* algorithm initialization -----------
			SortedList open = new SortedList();
			ArrayList closed = new ArrayList();
			Stack stack = new Stack();

			PathNode temp = new PathNode(ptStart.X, ptStart.Y);
			temp.G = 0;
			temp.H = calcRouteHeuristics(ptStart, ptEnd);
			temp.F = temp.G + temp.H;
			open.Add(temp, temp);
			gridOpen[temp.X, temp.Y] = temp;

			// setup A* cost function
			int adjcCost = flowChart.RoutingOptions.LengthCost;
			int turnCost = flowChart.RoutingOptions.TurnCost;

			PathNode best = null;
			bool found = false;
			int iterations = 0;
			for ( ; ; )
			{
				iterations++;

				// Get the best node from the open list
				if (open.Count == 0) break;
				PathNode pstmp = open.GetByIndex(0) as PathNode;

				open.RemoveAt(0);
				gridOpen[pstmp.X, pstmp.Y] = null;

				closed.Add(pstmp);
				gridClosed[pstmp.X, pstmp.Y] = pstmp;

				if ((best = pstmp) == null) break;

				// If best == destination -> path found
				if (best.X == ptEnd.X && best.Y == ptEnd.Y)
				{
					found = true;
					break;
				}

				// Generate best's successors
				int x = best.X;
				int y = best.Y;

				int[,] off = new int[4, 2] { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
				for (i = 0; i < 4; i++)
				{
					byte localCost = grid[x + off[i, 0], y + off[i, 1]];
					if (localCost == 255)
						continue;

					int g = best.G + adjcCost + localCost;
					bool straight = best.Parent == null ||
						(best.Parent.Y == best.Y && off[i, 1] == 0) ||
						(best.Parent.X == best.X && off[i, 0] == 0);
					if (best.Parent == null && oNearest >= 0 && (
						oNearest < 2 && off[i, 1] == 0 || oNearest >= 2 && off[i, 1] == 1))
						straight = false;
					if (!straight) g += turnCost;

					PathNode check = null;

					// if the successor is an open node, add it to the path
					check = gridOpen[x + off[i, 0], y + off[i, 1]];
					if (check != null)
					{
						best.Children[best.ChildCount++] = check;

						// and update its cost if now it is reached via a better path
						if (g < check.G)
						{
							open.Remove(check);		// keep sorted
							check.Parent = best;
							check.G = g;
							check.F = g + check.H;
							open.Add(check, check);	// keep sorted
						}
					}
					else
					{
						// if the successor is a closed node, add it to the path
						check = gridClosed[x + off[i, 0], y + off[i, 1]];
						if (check != null)
						{
							best.Children[best.ChildCount++] = check;

							// and update its cost if now it is reached via a better path
							if (g < check.G)
							{
								check.Parent = best;
								check.G = g;
								check.F = g + check.H;

								// and update its child items
								int gg = check.G;
								int cc = check.ChildCount;
								PathNode kid = null;
								for (int j = 0; j < cc; j++)
								{
									kid = check.Children[j];

									int gi = adjcCost;
									straight = check.Parent == null ||
										(check.Parent.Y == check.Y && check.Y == kid.Y) ||
										(check.Parent.X == check.X && check.X == kid.X);
									if (!straight) gi += turnCost;

									if (g + gi < kid.G)
									{
										bool wasOpen = gridOpen[kid.X, kid.Y] != null;
										if (wasOpen) open.Remove(kid);	// keep sorted

										kid.G = g + gi;
										kid.F = kid.G + kid.H;
										kid.Parent = check;
										stack.Push(kid);

										if (wasOpen) open.Add(kid, kid);
									}
								}
								PathNode parent;
								while (stack.Count > 0)
								{
									parent = stack.Pop() as PathNode;
									cc = parent.ChildCount;
									for (int j = 0; j < cc; j++)
									{
										kid = parent.Children[j];

										int gi = adjcCost;
										straight = parent.Parent == null ||
											(parent.Parent.Y == parent.Y && parent.Y == kid.Y) ||
											(parent.Parent.X == parent.X && parent.X == kid.X);
										if (!straight) gi += turnCost;

										if (parent.G + gi < kid.G)
										{
											bool wasOpen = gridOpen[kid.X, kid.Y] != null;
											if (wasOpen) open.Remove(kid);	// keep sorted

											kid.G = parent.G + gi;
											kid.F = kid.G + kid.H;
											kid.Parent = parent;
											stack.Push(kid);

											if (wasOpen) open.Add(kid, kid);
										}
									}
								}
							}
						}
						else
						{
							// haven't considered this grid square by now
							// create and initialize a path node for it 
							Point current = new Point(x + off[i, 0], y + off[i, 1]);
							PathNode newNode = new PathNode(current.X, current.Y);
							newNode.Parent = best;
							newNode.G = g;
							newNode.H = calcRouteHeuristics(current, ptEnd);
							newNode.F = newNode.G + newNode.H;

							// add it to the list of open nodes to be evaluated later
							open.Add(newNode, newNode);
							gridOpen[newNode.X, newNode.Y] = newNode;

							// add to the path
							best.Children[best.ChildCount++] = newNode;
						}
					}
				}
			}

			if (found)
			{
				PtCollection current = new PtCollection(0);

				current.Add(new Point((int)((points[points.Count - 1].X - bounds.X) / gridSize),
					(int)((points[points.Count - 1].Y - bounds.Y) / gridSize)));
				while (best != null)
				{
					current.Add(new Point(best.X, best.Y));
					best = best.Parent;
				}
				current.Add(new Point((int)((points[0].X - bounds.X) / gridSize),
					(int)((points[0].Y - bounds.Y) / gridSize)));

				// Remove all unneeded points
				Point pt1, pt2, pt3;
				for (i = 1; i < current.Count - 1;)
				{
					pt1 = current[i - 1];
					pt2 = current[i];
					pt3 = current[i + 1];

					if (pt1.X == pt2.X && pt2.X == pt3.X)
						current.RemoveAt(i);
					else if(pt1.Y == pt2.Y && pt2.Y == pt3.Y)
						current.RemoveAt(i);
					else
						i++;
				}

				// Save the first and last points of the arrow
				PointF ptFirst = points[0];
				PointF ptLast = points[points.Count - 1];

				// no perp. arrows on a single line
				if (style == ArrowStyle.Cascading && current.Count == 2 &&
					ptFirst.X != ptLast.X && ptFirst.Y != ptLast.Y)
				{
					Point orgPt = current[0];
					Point trgPt = current[current.Count-1];
					if (orgPt.X == trgPt.X || orgPt.Y == trgPt.Y)
					{
						Point insPt = new Point(
							(orgPt.X + trgPt.X) / 2, (orgPt.Y + trgPt.Y) / 2);
						current.Insert(1, insPt);
						current.Insert(1, insPt);
					}
				}

				// Re-segment the arrow
				points = new PointCollection(current.Count);
				points[0] = ptFirst;
				points[points.Count - 1] = ptLast;

				// Assign the points from the path
				i = current.Count - 1;
				i--; // Skip the first point
				while (i > 0)
				{
					Point pt = current[i];
					PointF ptDoc = new PointF(0, 0);
					ptDoc.X = bounds.X + pt.X * gridSize + gridSize / 2;
					ptDoc.Y = bounds.Y + pt.Y * gridSize + gridSize / 2;

					if (i == 1)
					{
						// Align to the last point
						if (pt.Y == current[0].Y)
							ptDoc.Y = ptLast.Y;
						else
							ptDoc.X = ptLast.X;
					}
					if (i == current.Count - 2)
					{
						// Align to the first point
						if (pt.Y == current[current.Count - 1].Y)
							ptDoc.Y = ptFirst.Y;
						else
							ptDoc.X = ptFirst.X;

						if (style == ArrowStyle.Cascading)
							cascadeStartHorizontal = (ptDoc.X != ptFirst.X);
					}

					points[current.Count - i - 1] = ptDoc;
					i--;
				}

				PointF ptf, ptf1, ptf2, ptf3;

				// If the line is perpendicular make it at least 2 segments
				if(style == ArrowStyle.Cascading && points.Count == 2)
				{
					ptf1 = points[0];
					ptf2 = points[points.Count - 1];
					ptf = ptf1;
					if (cascadeStartHorizontal)
						ptf.X = ptf2.X;
					else
						ptf.Y = ptf2.Y;
					points.Insert(1, ptf);
				}

				// If the line is straight there might be more unneeded points
				if (style == ArrowStyle.Polyline)
				{
					i = 0;
					while(i < points.Count - 2)
					{
						ptf1 = points[i];
						ptf2 = points[i + 2];

						ChartObject obj = flowChart.objectIntersectedBy(ptf1, ptf2,
							orgnLink.getNode(), destLink.getNode());
						if(obj == null)
							points.RemoveAt(i + 1);
						else
							i++;
					}
				}

				// If the line is bezier, smooth it a bit
				if (style == ArrowStyle.Bezier)
				{
					PointCollection newPoints = new PointCollection(0);
					newPoints.Add(points[0]);
					i = 0;
					while(i < points.Count - 2)
					{
						ptf1 = points[i];
						ptf2 = points[i + 1];

						newPoints.Add(ptf2);
						newPoints.Add(ptf2);
						if(i != points.Count - 3)
						{
							ptf3 = points[i + 2];
							ptf = new PointF((ptf2.X + ptf3.X) / 2, (ptf2.Y + ptf3.Y) / 2);
							newPoints.Add(ptf);
						}
						else
						{
							newPoints.Add(points[i + 2]);
						}
						i += 1;
					}

					if (newPoints.Count == 1)
					{
						newPoints = new PointCollection(4);

						ptf1 = points[0];
						ptf2 = points[points.Count - 1];
						ptf = new PointF((ptf1.X + ptf2.X) / 2, (ptf1.Y + ptf2.Y) / 2);
						newPoints[0] = ptf1;
						newPoints[1] = ptf;
						newPoints[2] = ptf;
						newPoints[3] = ptf2;
					}

					points.Clear();
					points = newPoints;
				}

				// Update SegmentCount property value
				if (style == ArrowStyle.Bezier)
					segmentCount = (short)((points.Count - 1) / 3);
				else
					segmentCount = (short)(points.Count - 1);
			}
			else
			{
				// No path found -> reset the arrow, leaving as little points as possible
				int ptsToLeave = 2;
				if (style == ArrowStyle.Cascading)
					ptsToLeave = 4;
				else if (style == ArrowStyle.Bezier)
					ptsToLeave = 4;

				if (style == ArrowStyle.Cascading)
				{
					cascadeOrientation = Orientation.Auto;
					segmentCount = 3;
				}
				else
					segmentCount = 1;

				while (points.Count > ptsToLeave)
					points.RemoveAt(1);

				if (style == ArrowStyle.Cascading && points.Count == 3)
					segmentCount = 2;

				updatePoints(points[points.Count - 1]);
			}

			updateArrowHeads();

			if (subordinateGroup != null)
			{
				subordinateGroup.onSegmentsChanged();
				subordinateGroup.updateObjects(new InteractionState(this, -1, Action.Modify));
			}

			resetCrossings();
			updateText();

			flowChart.fireArrowRoutedEvent(this);
		}
Пример #11
0
		private void restoreSegments(ArrowSegmentsState state)
		{
			points = state.controlPoints.Clone();
			segmentCount = state.segmentCount;
			cascadeStartHorizontal = state.cascadeStartHorizontal;
		}
Пример #12
0
		private void setSegments(short segments)
		{
			int ctrlPoints = 2;

			switch (style)
			{
				case ArrowStyle.Bezier:
					ctrlPoints = segments*3 + 1;
					break;
				case ArrowStyle.Polyline:
					ctrlPoints = segments + 1;
					break;
				case ArrowStyle.Cascading:
					ctrlPoints = segments + 1;
					break;
			}

			points = new PointCollection(ctrlPoints);
			segmentCount = segments;

			if (subordinateGroup != null)
				subordinateGroup.onSegmentsChanged();
		}
Пример #13
0
		// ************ drawing ************

		internal void drawArrowSegments(Graphics g,
			System.Drawing.Pen p, System.Drawing.Brush b,
			System.Drawing.Pen pHeads, bool shadow, bool custom)
		{
			PointCollection pts = points;
			float xoff = shadow ? ShadowOffsetX : 0;
			float yoff = shadow ? ShadowOffsetY : 0;

			// offset if drawing shadow
			if (shadow)
			{
				pts = new PointCollection(points.Count);
				for (int i = 0; i < pts.Count; ++i)
				{
					pts[i] = new PointF(
						points[i].X + xoff, points[i].Y + yoff);
				}
			}

			if (custom && (customDraw == CustomDraw.Full ||
				(customDraw == CustomDraw.ShadowOnly && shadow)))
			{
				// call the custom draw function
				flowChart.drawArrow(g, this, shadow, pts);
			}
			else
			{
				// draw the arrow's line
				if (style == ArrowStyle.Bezier)
				{
					g.DrawBeziers(p, pts.getArray());
				}
				else
				{
					float mm = Constants.getMillimeter(flowChart.MeasureUnit);
					float pathThresh = mm / 3;
					if (!drawCrossings || flowChart.ArrowCrossings ==
						MindFusion.FlowChartX.ArrowCrossings.Straight)
					{
						if (flowChart.RoundedArrows)
						{
							DrawRoundedPolyline(g, p, pts.getArray(),
								flowChart.RoundedArrowsRadius, true, pathThresh, null);
						}
						else
						{
							g.DrawLines(p, pts.getArray());
						}
					}
					else
					{
						float crad = flowChart.CrossingRadius;

						ArrowCrossings crossings = getCrossings();
						object startPoint = null;

						GraphicsPath gpath = pen.Width > pathThresh ?
							new GraphicsPath() : null;

						for (int i = 0; i < segmentCount; ++i)
						{
							PointCollection pc = crossings.segmentCrossings[i] as PointCollection;
							if (pc.Count > 0)
							{
								for (int j = 0; j < pc.Count - 1; ++j)
								{
									PointF pt1 = pc[j];
									PointF pt2 = pc[j + 1];
									pt1.X += xoff; pt1.Y += yoff;
									pt2.X += xoff; pt2.Y += yoff;

									if (startPoint != null)
										pt1 = (PointF)startPoint;

									startPoint = null;

									if (j % 2 == 0)
									{
										// The subsegment between two crossings or
										// between a crossing and a segment end-point
										if (flowChart.RoundedArrows)
										{
											// Check if this is the last subsegment
											// in this segment. If that is the case,
											// and this is not the last segment of the
											// arrow, draw rounded arrow
											if (j == pc.Count - 2 && i != segmentCount - 1)
											{
												// The third point in the poly is
												// the second point of the next segment
												// if it does not have crossings, or
												// the second point of the crossings array
												int ni = i + 2;
												PointF next = pts[ni];
												while (Math.Abs(next.X - pt2.X) + Math.Abs(next.Y - pt2.Y) < 0.00001f)
												{
													ni++;
													if (ni == pts.Count)
														break;

													next = pts[ni];
												}

												if (ni == pts.Count)
												{
													if (gpath != null)
														gpath.AddLine(pt1, pt2);
													else
														g.DrawLine(p, pt1, pt2);
												}
												else
												{
													PointCollection nextPc = crossings.segmentCrossings[ni - 1] as PointCollection;
													if (nextPc.Count > 2)
													{
														next = nextPc[1];
														next.X += xoff;
														next.Y += yoff;
													}

													PointF[] triPoints = new PointF[]
												{
													pt1, pt2, next
												};

													startPoint = DrawRoundedPolyline(g, p, triPoints,
														flowChart.RoundedArrowsRadius, false, pathThresh, gpath);
												}
											}
											else
											{
												if (gpath != null)
													gpath.AddLine(pt1, pt2);
												else
													g.DrawLine(p, pt1, pt2);
											}
										}
										else
										{
											if (gpath != null)
												gpath.AddLine(pt1, pt2);
											else
												g.DrawLine(p, pt1, pt2);
										}
									}
									else
									{
										if (flowChart.ArrowCrossings ==
											MindFusion.FlowChartX.ArrowCrossings.Arcs)
										{
											float rad = Utilities.Distance(pt1, pt2) / 2;

											float aa = 0;
											float rr = 0;
											Geometry.Geometry2D.Convert.DekartToPolar(
												pt1, pt2, ref aa, ref rr);

											PointF[] centers = new PointF[] { PointF.Empty, PointF.Empty };
											Geometry.Geometry2D.Convert.PolarToDekart(
												pt1, aa, crad, ref centers[0]);
											Geometry.Geometry2D.Convert.PolarToDekart(
												pt1, aa, 2 * rad - crad, ref centers[1]);

											PointF[] startPts = new PointF[] { pt1, PointF.Empty };
											PointF[] endPts = new PointF[] { PointF.Empty, pt2 };
											Geometry.Geometry2D.Convert.PolarToDekart(
												pt1, aa, 2 * crad, ref endPts[0]);
											Geometry.Geometry2D.Convert.PolarToDekart(
												pt1, aa, 2 * rad - 2 * crad, ref startPts[1]);

											float angle = aa;
											if (angle < 90)
												angle += 180;

											RectangleF rc = RectangleF.FromLTRB(
												centers[0].X - crad,
												centers[0].Y - crad,
												centers[0].X + crad,
												centers[0].Y + crad);

											float ded = 0 * 90;
											if (aa < 90)
												ded = 90 - ded;

											float start = 180 - angle - ded;
											float sweep = -90;
											if (aa < 90)
											{
												start += sweep;
												sweep = -sweep;
											}

											if (gpath != null)
												gpath.AddArc(rc, start, sweep);
											else
												g.DrawArc(p, rc, start, sweep);

											PointF p1 = PointF.Empty;
											PointF p2 = PointF.Empty;
											Geometry.Geometry2D.Convert.PolarToDekart(
												centers[0], angle - 90, crad, ref p1);
											Geometry.Geometry2D.Convert.PolarToDekart(
												centers[1], angle - 90, crad, ref p2);

											if (gpath != null)
												gpath.AddLine(p1, p2);
											else
												g.DrawLine(p, p1, p2);

											rc = RectangleF.FromLTRB(
												centers[1].X - crad,
												centers[1].Y - crad,
												centers[1].X + crad,
												centers[1].Y + crad);

											ded = 1 * 90;
											if (aa < 90)
												ded = 90 - ded;

											start = 180 - angle - ded;
											sweep = -90;
											if (aa < 90)
											{
												start += sweep;
												sweep = -sweep;
											}

											if (gpath != null)
												gpath.AddArc(rc, start, sweep);
											else
												g.DrawArc(p, rc, start, sweep);

										}
										else
										{
											// Start new figure in the graph,
											// thus preventing the graph
											// to automatically connect broken
											// lines and losing break-offs
											if (gpath != null)
												gpath.StartFigure();
										}
									}
								}
							}
							else
							{
								if (gpath != null)
									gpath.AddLine(pts[i], pts[i+1]);
								else
									g.DrawLine(p, pts[i], pts[i+1]);
							}
						}

						if (gpath != null)
						{
							gpath.Flatten(new Matrix(), 0.05f);
							g.DrawPath(p, gpath);
							gpath.Dispose();
						}
					}
				}

				// draw arrowheads, intermediate are skipped for asBezier arrows
				ahBase.draw(g, pHeads, b, xoff, yoff);
				if (style != ArrowStyle.Bezier && arrowInterm != ArrowHead.None)
				{
					for (int i = 0; i < points.Count - 1; i++)
					{
						PointF pt1 = pts[i];
						PointF pt2 = new PointF((pt1.X + pts[i+1].X)/2, (pt1.Y + pts[i+1].Y)/2);
					
						headTemplates[(int)arrowInterm].recalcArrowHead(ahInterm, pt1, pt2);
						ahInterm.draw(g, pHeads, b, 0, 0);
					}
				}
				ahHead.draw(g, pHeads, b, xoff, yoff);

				// additional custom draw type
				if (custom && customDraw == CustomDraw.Additional)
					flowChart.drawArrow(g, this, false, pts);
			}
		}
Пример #14
0
		internal override void completeModify(PointF end, InteractionState ist)
		{
			// make sure the modification does not propagate through endless recursion
			if (cycleProtect) return;
			cycleProtect = true;

			if (!(snapToNodeBorder && objNewDest != null))
				end = flowChart.AlignPointToGrid(end);

			// snap to anchor point 
			Node objNode = null;
			if (modifyHandle == 0 || modifyHandle == points.Count-1)
			{
				objNode = flowChart.GetNodeAt(end);

				// align to node border if that's enabled
				if (snapToNodeBorder && objNode != null)
					end = objNode.getNearestOutlinePt(end);

				// align to anchor point
				int idx = -1;
				if (objNode != null &&
					flowChart.SnapToAnchor == SnapToAnchor.OnCreateOrModify)
					end = objNode.getAnchor(end, this, modifyHandle != 0, ref idx);
					
				if (modifyHandle == 0) orgnAnchor = idx; else destAnchor = idx;
			}

			// Route only if either the first or the last point is modified
			bool shouldRoute = (modifyHandle == 0 || modifyHandle == points.Count - 1);

			// update ctrl. point position
			base.completeModify(end, ist);
			points[modifyHandle] = end;
			updateRelatedPoints(end, ist);

			// update the links if the origin object has changed
			if (modifyHandle == 0)
			{
				PointF pt = points[0];
				if (objNode == null)
					objNode = flowChart.GetNodeAt(pt);
				if (objNode == null)
					objNode = flowChart.Dummy;
				if (objNode != null && orgnLink.linkChanges(objNode, pt))
				{
					orgnLink.removeArrowFromObj();
					orgnLink = null;
					orgnLink = objNode.createLink(this, pt, false);
					orgnLink.addArrowToObj();
					reflexive = orgnLink.sameNode(destLink);
				}
				orgnLink.saveEndRelative();
			}
			else

			// update the links if the target object has changed
			if (modifyHandle == points.Count-1)
			{
				PointF pt = points[points.Count-1];
				if (objNode == null)
					objNode = flowChart.GetNodeAt(pt);
				if (objNode == null)
					objNode = flowChart.Dummy;
				if (objNode != null && destLink.linkChanges(objNode, pt))
				{
					destLink.removeArrowFromObj();
					destLink = null;
					destLink = objNode.createLink(this, pt, true);
					destLink.addArrowToObj();
					reflexive = destLink.sameNode(orgnLink);
				}
				destLink.saveEndRelative();
			}
			else

			// combine arrow segments ?
			{
				PointF ptPrev = points[modifyHandle - 1];
				PointF ptCurr = points[modifyHandle];
				PointF ptNext = points[modifyHandle + 1];

				// for polylines: if the angle between them is ~180
				if (style == ArrowStyle.Polyline && flowChart.AllowSplitArrows)
				{
					PointCollection pts = new PointCollection(2);
					pts.SetAt(0, ptPrev);
					pts.SetAt(1, ptNext);

					float dx = ptNext.X - ptPrev.X;
					float dy = ptNext.Y - ptPrev.Y;
					float len = (float)Math.Sqrt(dx*dx + dy*dy);

					float d = Utilities.distToPolyline(ptCurr, pts, 2);

					if (d*35 < len)
					{
						points.RemoveAt(modifyHandle);
						segmentCount--;
						if (subordinateGroup != null)
							subordinateGroup.onArrowSplit(false, modifyHandle, 1);
					}
				}

				// combine segments of cascading arrows if two adjacent control points overlap
				if (style == ArrowStyle.Cascading && segmentCount > 3 &&
					flowChart.AllowSplitArrows)
				{
					int toDel = -1;

					if (modifyHandle > 1 && flowChart.mergePoints(ptPrev, ptCurr))
						toDel = modifyHandle - 1;
					if (modifyHandle < points.Count - 2 && flowChart.mergePoints(ptNext, ptCurr))
						toDel = modifyHandle;

					if (toDel != -1)
					{
						points.RemoveAt(toDel);
						points.RemoveAt(toDel);
						segmentCount -= 2;
						alignCascadingSegments(toDel);
						updateEndPtsPrp();
						if (subordinateGroup != null)
							subordinateGroup.onArrowSplit(false, toDel, 2);
					}
				}
			}

			if (reflexive && (style == ArrowStyle.Polyline && segmentCount == 1 ||
				style == ArrowStyle.Cascading && segmentCount == 2))
			{
				setReflexive();
				if (subordinateGroup != null)
					subordinateGroup.endModification();
				cycleProtect = false;
				objNewDest = null;
				return;
			}

			if (shouldRoute && autoRoute && flowChart.rerouteArrow(this))
				doRoute();

			updateArrowHeads();
			if (subordinateGroup != null)
				subordinateGroup.endModification();
			resetCrossings();
			updateText();

			flowChart.fireObjModified(this, end, modifyHandle);
			cycleProtect = false;
			objNewDest = null;
		}
Пример #15
0
		public ArrowDrawArgs(Graphics g, Arrow arrow, bool shadow, PointCollection points) :
			base(arrow)
		{
			this.graphics = g;
			this.shadow = shadow;
			this.points = points;
		}
Пример #16
0
		private string createPolyArea(PointCollection points)
		{
			string strCoords = "\"";
			Point pt = new Point(0,0);
            
			for (int j = 0; j < points.Count; ++j)
			{
				PointF docPt = points[j];
				docPt.X -= docOffsetX;
				docPt.Y -= docOffsetY;

				pt = DocToClient(docPt);
				strCoords += pt.X.ToString() + "," + pt.Y.ToString();
				if (j < points.Count - 1) strCoords += ",";
			}
            
			strCoords = strCoords + "\"";

			return "\"POLY\" COORDS=" + strCoords;
		}
Пример #17
0
		internal static float distToPolyline(PointF pt, PointCollection line_pts, int nPoints)
		{
			int segmNum = 0;
			return distToPolyline(pt, line_pts, nPoints, ref segmNum);
		}
Пример #18
0
		private ArrowCrossings getCrossings()
		{
			float crad = flowChart.CrossingRadius;
			RectangleF rcArrow = getBoundingRect();
			PointCollection intersections = new PointCollection(0);

			ArrowCrossings ac = (ArrowCrossings)getData(Constants.ARROW_CROSSINGS);
			if (ac == null)
			{
				ac = new ArrowCrossings(segmentCount);
				setData(Constants.ARROW_CROSSINGS, ac);

				// z index where this arrow is or will be placed
				int z = ZIndex;
				if (!constructed)
					z = flowChart.Objects.Count;

				// get the arrows which should be checked for intersections
				ArrowCollection arrows;
				if (flowChart.ArrowCrossings ==
					MindFusion.FlowChartX.ArrowCrossings.Arcs)
					arrows = flowChart.getArrowsFromZ(true, z);
				else
					arrows = flowChart.getArrowsFromZ(false, z);

				// check each segment
				for (int sgt = 0; sgt < segmentCount; ++sgt)
				{
					PointF pt1 = Points[sgt];
					PointF pt2 = Points[sgt+1];
					if (pt1 == pt2) continue;

					// find intersecting points with each arrow
					for (int i = 0; i < arrows.Count; ++i)
					{
						Arrow arrow = arrows[i];
						if (!arrow.Visible || arrow.Style == ArrowStyle.Bezier)
							continue;

						// dont check segments if arrow bounding rects dont intersect at all
						RectangleF rcTest = arrow.getBoundingRect();
						if (!rcTest.IntersectsWith(rcArrow))
							continue;

						for (int test = 0; test < arrow.SegmentCount; ++test)
						{
							PointF testPt1 = arrow.Points[test];
							PointF testPt2 = arrow.Points[test+1];
							if (testPt1 == testPt2) continue;

							PointF intersection = new PointF(0, 0);
							if (Utilities.segmentIntersect(pt1, pt2,
								testPt1, testPt2, ref intersection))
							{
								if (Utilities.Distance(pt1, intersection) > crad &&
									Utilities.Distance(pt2, intersection) > crad)
									intersections.Add(intersection);
							}
						}
					}

					// sort by distance to the first point
					intersections.Sort(new CloserDistance(pt1));

					// add radial intersections to the runtime intersection data
					CloserDistance closer = new CloserDistance(pt1);
					PointCollection rintr = ac.segmentCrossings[sgt] as PointCollection;
					rintr.Add(pt1);
					for (int ptc = 0; ptc < intersections.Count; ++ptc)
					{
						PointF ptRes1, ptRes2, pt = intersections[ptc];
						ptRes1 = ptRes2 = pt;
						RectangleF rc = RectangleF.FromLTRB(
							pt.X - crad, pt.Y - crad, pt.X + crad, pt.Y + crad);
						Utilities.getEllipseIntr(rc, pt1, pt, ref ptRes1);
						Utilities.getEllipseIntr(rc, pt2, pt, ref ptRes2);
						if (closer.Compare(ptRes1, ptRes2) < 0)
						{
							rintr.Add(ptRes1);
							rintr.Add(ptRes2);
						}
						else
						{
							rintr.Add(ptRes2);
							rintr.Add(ptRes1);
						}
					}
					rintr.Add(pt2);

					// Check if there are intersection that overlap
					for (int i = 1; i < rintr.Count - 2; )
					{
						PointF p1 = rintr[i];
						PointF p2 = rintr[i + 1];

						if (closer.Compare(p1, p2) > 0 ||
							Utilities.Distance(p1, p2) < Constants.getMillimeter(flowChart.MeasureUnit) / 2)
						{
							// Remove these points
							rintr.RemoveAt(i);
							rintr.RemoveAt(i);
						}
						else
						{
							i++;
						}
					}

					intersections.Clear();

				}	// for (int sgt = 0; sgt < GetSegments(); ++sgt)
			}

			return ac;
		}
Пример #19
0
		public static PointCollection approxBezier(PointF[] points, int startIdx, int quality)
		{
			PointCollection approximation = new PointCollection(0);
			double epsilon = 1.0 / quality;

			// get the points defining the curve
			float x0 = points[0 + startIdx].X;
			float y0 = points[0 + startIdx].Y;
			float x1 = points[1 + startIdx].X;
			float y1 = points[1 + startIdx].Y;
			float x2 = points[2 + startIdx].X;
			float y2 = points[2 + startIdx].Y;
			float x3 = points[3 + startIdx].X;
			float y3 = points[3 + startIdx].Y;

			// x(t) = (1-t)^3 x0 + 3t(1-t)^2 x1 + 3t^2 (1-t) x2 + t^3 x3
			// y(t) = (1-t)^3 y0 + 3t(1-t)^2 y1 + 3t^2 (1-t) y2 + t^3 y3
			for (double t = 0; t <= 1.0; t += epsilon)
			{
				double q0 = (1-t)*(1-t)*(1-t);
				double q1 = 3*t*(1-t)*(1-t);
				double q2 = 3*t*t*(1-t);
				double q3 = t*t*t;
				double xt = q0*x0 + q1*x1 + q2*x2 + q3*x3;
				double yt = q0*y0 + q1*y1 + q2*y2 + q3*y3;

				// draw straight line between last two calculated points
				approximation.Add(new PointF((float)xt, (float)yt));
			}

			return approximation;
		}
Пример #20
0
		internal override PointCollection getOutlinePoly()
		{
			PointCollection poly = new PointCollection(0);
			GraphicsPath arrowPath = new GraphicsPath(FillMode.Alternate);

			// draw the arrow's line
			if (style == ArrowStyle.Bezier)
			{
				arrowPath.AddBeziers(points.getArray());
			}
			else
			{
				arrowPath.AddLines(points.getArray());
			}

			System.Drawing.Pen widenPen = new System.Drawing.Pen(Color.Black,
				2 * Constants.getMillimeter(flowChart.MeasureUnit));
			arrowPath.Widen(widenPen);
			arrowPath.Flatten();
			poly.AddRange(arrowPath.PathPoints);
			widenPen.Dispose();
			arrowPath.Dispose();

			return poly;
		}
Пример #21
0
		internal static float distToBezier(PointF pt, PointCollection bez_pts, int nPoints)
		{
			int nSplineNum = nPoints / 3;
			float nRes = 1000000;

			for (int nSpline = 0; nSpline < nSplineNum; ++nSpline)
			{
				double x0 = bez_pts[nSpline*3+0].X;
				double y0 = bez_pts[nSpline*3+0].Y;
				double x1 = bez_pts[nSpline*3+1].X;
				double y1 = bez_pts[nSpline*3+1].Y;
				double x2 = bez_pts[nSpline*3+2].X;
				double y2 = bez_pts[nSpline*3+2].Y;
				double x3 = bez_pts[nSpline*3+3].X;
				double y3 = bez_pts[nSpline*3+3].Y;

				double a3 = (x3 - x0 + 3*(x1-x2)) / 8;
				double b3 = (y3 - y0 + 3*(y1-y2)) / 8;
				double a2 = (x3 + x0 - x1 - x2) * 3 / 8;
				double b2 = (y3 + y0 - y1 - y2) * 3 / 8;
				double a1 = (x3 - x0) / 2 - a3;
				double b1 = (y3 - y0) / 2 - b3;
				double a0 = (x3 + x0) / 2 - a2;
				double b0 = (y3 + y0) / 2 - b2;

				double x4 = pt.X;
				double y4 = pt.Y;

				double s1, s=0, u1, u2, z=0, z1, z2;
				s1 = 0;
				u2 = u1 = -1.0;
				z1 = z2 = 0;

				double stepsize = 2.0 / 9;
				double u = 0;
				for (u = -1.0; u < 1.0; u += stepsize)
				{
					calcBezierCoef(ref a0, ref a1, ref a2, ref a3, ref b0, ref b1, ref b2, ref b3, ref u, ref s, ref z, ref x4, ref y4);
					if (Math.Abs(s) < 0.00001)
					{
						u1 = u; z1 = z; s1 = s; break;
					}
					if (Math.Abs(u + 1.0) < 0.00001)
					{
						u1 = u; z1 = z; s1 = s;
					}
					if (s < s1)
					{
						u1 = u; z1 = z; s1 = s;
					}
				}

				if (Math.Abs(s1) > 0.00001)
				{
					u = u1 + stepsize;
					if (u > 1.0) u = 1.0 - stepsize;
					for(int cnt = 0 ; cnt < 20; cnt++)
					{
						calcBezierCoef(ref a0, ref a1, ref a2, ref a3, ref b0, ref b1, ref b2, ref b3, ref u, ref s, ref z, ref x4, ref y4);
						if (Math.Abs(s) < 0.00001) break;
						if (Math.Abs(z) < 0.00001) break;
						u2 = u;
						z2 = z;
						double temp = z2 - z1;
						if (Math.Abs(temp) > 0.00001)
						{
							u = (z2*u1 - z1*u2) / temp;
						}
						else
						{
							u = (u1 + u2) / 2;
						}
						if (u > 1.0)
						{
							u = 1.0;
						}
						else if (u < -1.0)
						{
							u = -1.0;
						}
						if (Math.Abs(u - u2) < 0.0001) break;
						u1 = u2;
						z1 = z2;
					}
				}

				if (nRes > Math.Sqrt(s)) nRes = (float)Math.Sqrt(s);
				if (nRes == 0) return 0;
			}

			return nRes;
		}
Пример #22
0
    internal static bool CompareControlPoints(PointCollection pointCollection, List<SysCAD.Protocol.Point> list)
    {
      if (pointCollection.Count == list.Count) return false;

      for (int i = 0; i < list.Count; i++)
      {
        if (pointCollection[i].X != list[i].X) return false;
        if (pointCollection[i].Y != list[i].Y) return false;
      }

      return true;
    }
Пример #23
0
		internal override PointCollection getOutlinePoly()
		{
			RectangleF br = BoundingRect;

			PointCollection points = new PointCollection(0);
			points.Add(new PointF(br.Left, br.Top));
			points.Add(new PointF(br.Right, br.Top));
			points.Add(new PointF(br.Right, br.Bottom));
			points.Add(new PointF(br.Left, br.Bottom));
			return points;
		}
Пример #24
0
		internal void onArrowSplit(bool added, int idx, int cnt)
		{
			if (added)
			{
				foreach (Attachment attc in attachments)
				{
					switch (attc.type)
					{
					case AttachTo.ArrowPoint:
						{
							int point = attc.attData;
							if (point >= idx)
								attc.attData += cnt;
						}
						break;
					case AttachTo.ArrowSegment:
						{
							int segment = attc.attData;
							if (segment >= idx)
								attc.attData += cnt;
						}
						break;
					}

				}	// for
			}
			else
			{
				foreach (Attachment attc in attachments)
				{
					switch (attc.type)
					{
					case AttachTo.ArrowPoint:
						{
							int point = attc.attData;
							if (point >= idx)
							{
								if (point < idx + cnt)
									attc.attData = idx;
								else
									attc.attData -= cnt;
							}
						}
						break;
					case AttachTo.ArrowSegment:
						{
							int segment = attc.attData;
							if (segment >= idx)
							{
								if (segment < idx + cnt)
									attc.attData = idx - 1;
								else
									attc.attData -= cnt;
								if (attc.attData < 0)
									attc.attData = 0;
							}
						}
						break;
					}

				}	// for
			}

			prevPoints = ((Arrow)mainObj).Points.Clone();
		}
Пример #25
0
		public PointCollection Clone()
		{
			PointCollection copy = new PointCollection(0);
			foreach (PointF pt in InnerList)
				copy.Add(pt);

			return copy;
		}
Пример #26
0
		/// <summary>
		/// Has to be called by the main object when its state is restored due to undo/redo.
		/// </summary>
		internal void onRestoreState()
		{
			if (mainObj.getType() == ItemType.Arrow)
			{
				prevPoints = ((Arrow)mainObj).Points.Clone();
			}
			else
			{
				prevRect = mainObj.getBoundingRect();
				prevRotation = (mainObj as Node).rotation();
			}
		}
Пример #27
0
		/// <summary>
		/// Converts PointCollection object into point array
		/// </summary>
		/// <param name="ptc">PointCollection to be converted</param>
		/// <returns>Corresponded point array</returns>
		PointF[] PtColl2Pts(PointCollection ptc)
		{
			PointF[] pts = null;
			try
			{
				
				pts = new PointF[ptc.Count];
				for (int i=0;i<ptc.Count;i++)
				{
					pts[i]=ptc[i];
					pts[i].Y = m_FlowChart.DocExtents.Height - ptc[i].Y;
				}
			}
			catch ( Exception ex)
			{
				m_status = ex.Message;
				Trace.WriteLine(String.Format("{0} error {1}\n","DxfHelper.PtColl2Pts",ex.Message));
			
			}

			Trace.WriteLine(String.Format("PtColl2Pts {0} -> {1}", ptc.Count, pts.Length));
			return pts;
		}
Пример #28
0
		internal override PointCollection getOutlinePoly()
		{
			RectangleF br = BoundingRect;

			PointCollection points = new PointCollection(0);
			GraphicsPath gp = null;

			switch (style)
			{
				case BoxStyle.Rectangle:
				case BoxStyle.RoundedRectangle:
					points.Add(new PointF(br.Left, br.Top));
					points.Add(new PointF(br.Right, br.Top));
					points.Add(new PointF(br.Right, br.Bottom));
					points.Add(new PointF(br.Left, br.Bottom));
					break;
				case BoxStyle.Shape:
					gp = Shape.getPath(shapeData, rotation());
					gp.Flatten();
					points.AddRange(gp.PathPoints);
					gp.Dispose();
					break;
				case BoxStyle.Ellipse:
					points = Utilities.approxEllipse(br, 40);
					break;
				case BoxStyle.Rhombus:
					// calculate the vertex coordinates
					points.Add(new PointF((br.Left + br.Right) / 2, br.Top));
					points.Add(new PointF(br.Right, (br.Top + br.Bottom) / 2));
					points.Add(new PointF((br.Left + br.Right) / 2, br.Bottom));
					points.Add(new PointF(br.Left, (br.Top + br.Bottom) / 2));
					break;
				case BoxStyle.Delay:
					gp = Utilities.getDelaySymbol(br);
					gp.Flatten();
					points.AddRange(gp.PathPoints);
					gp.Dispose();
					break;
			}

			return points;
		}