Ejemplo n.º 1
0
        protected static new void DrawDecorator(DiagramPaintEventArgs e, IGeometryHost geometryHost, float rotation, PointD centerRight, LinkDecorator decorator)
        {
            SizeD size = LinkShapeGeometry.SizeDecorator;
#endif
            double offsetBy = 0d;
            bool   doOffset = false;
            ILinkDecoratorSettings settings = decorator as ILinkDecoratorSettings;
            if (settings != null)
            {
                size     = settings.DecoratorSize;
                offsetBy = settings.OffsetBy;
                doOffset = !VGConstants.FuzzZero(offsetBy, VGConstants.FuzzDistance);
            }
            Graphics   g              = e.Graphics;
            RectangleD boundingRect   = new RectangleD(centerRight.X - size.Width, centerRight.Y - (size.Height / 2), size.Width, size.Height);
            Matrix     rotationMatrix = g.Transform;
            float      offsetX        = 0f;
            float      offsetY        = 0f;
            if (doOffset)
            {
                double rotationRadians = rotation * Math.PI / 180;
                offsetX = (float)(offsetBy * Math.Cos(rotationRadians));
                offsetY = (float)(offsetBy * Math.Sin(rotationRadians));
                rotationMatrix.Translate(offsetX, offsetY);
            }
            rotationMatrix.RotateAt(rotation, PointD.ToPointF(centerRight));
            g.Transform = rotationMatrix;
            decorator.DoPaintShape(boundingRect, geometryHost, e);
            rotationMatrix.RotateAt(-rotation, PointD.ToPointF(centerRight));
            if (doOffset)
            {
                rotationMatrix.Translate(-offsetX, -offsetY);
            }
            g.Transform = rotationMatrix;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Pulled directly from Reflector disassembly
        /// </summary>
        private LineSegment[] CalculateSegments(IGeometryHost geometryHost, DiagramHitTestInfo hitTestInfo)
        {
            IBinaryLinkGeometryData data1       = geometryHost as IBinaryLinkGeometryData;
            EdgePointCollection     collection1 = data1.GeometryEdgePointsNoJumps;

            LineSegment[] segmentArray1 = new LineSegment[collection1.Count - 1];
            Pen           pen1          = geometryHost.GeometryStyleSet.GetPen(this.GetOutlinePenId(geometryHost));

            if (pen1 != null)
            {
                for (int num1 = 0; num1 < (collection1.Count - 1); num1++)
                {
                    RectangleD ed1 = GeometryHelpers.RectangleDFrom2Pts(collection1[num1].Point, collection1[num1 + 1].Point);
                    // In DSL Tools v8.2, GetHitTestTolerance is an instance method, but in DSL Tools v9.0, it is a static method.
                    // We call it without a qualifier here so that it will compile against both versions.
                    SizeD ed2 = GetHitTestTolerance(hitTestInfo);
                    if (ed1.Height < ed2.Height)
                    {
                        ed1.Inflate(0, (pen1.Width / 2f) + ed2.Height);
                    }
                    else if (ed1.Width < ed2.Width)
                    {
                        ed1.Inflate((pen1.Width / 2f) + ed2.Width, 0);
                    }
                    segmentArray1[num1] = new LineSegment(collection1[num1].Point, collection1[num1 + 1].Point, num1, num1 + 1, num1 == 0, (num1 + 1) == (collection1.Count - 1), ed1);
                }
            }
            return(segmentArray1);
        }
Ejemplo n.º 3
0
            /// <summary>
            /// Return a path modified to include any ER multiplicity decorators
            /// </summary>
            public override GraphicsPath GetPath(IGeometryHost geometryHost)
            {
                //TODO get this to work properly

                //GraphicsPath path = base.UninitializedPath;
                //path.Reset();

                //AssociationConnector connector = (AssociationConnector)geometryHost;

                //EdgePointCollection edgePoints;
                //int edgePointCount;
                //if (null != (edgePoints = connector.EdgePoints) &&
                //    1 < (edgePointCount = edgePoints.Count))
                //{
                //    PointD p1 = edgePoints[edgePointCount - 1].Point;
                //    PointD p2 = edgePoints[0].Point;

                //    path.AddLine(PointD.ToPointF(p1), PointD.ToPointF(p2));

                //    //DrawAssociationEnd(e, geometryHost, connector.FromShape, p2, midP, true, true);
                //    //DrawAssociationEnd(e, geometryHost, connector.ToShape, p1, midP, true, false);
                //}

                //return path;

                return(base.GetPath(geometryHost));
            }
Ejemplo n.º 4
0
        /// <summary>
        /// Gets the suggested connection points of this geometry.
        /// </summary>
        /// <value></value>
        public override PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost)
        {
            RectangleD boundingBox = this.GetPerimeterBoundingBox(geometryHost);

            return(new PointD[]
            {
                new PointD(boundingBox.Right, (boundingBox.Top + (boundingBox.Height / 2))),
            });
        }
        /// <summary>
        /// Gets the suggested connection points of this geometry.
        /// </summary>
        /// <value></value>
        public override PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost)
        {
            RectangleD boundingBox = this.GetPerimeterBoundingBox(geometryHost);

            return new PointD[] 
            {
                new PointD(boundingBox.Right, (boundingBox.Top + (boundingBox.Height / 2))),
            };
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Paint the composite shape decorators.
 /// </summary>
 /// <param name="bounds">Forwarded to composite decorators</param>
 /// <param name="shape">Forwarded to composite decorators</param>
 /// <param name="e">Forwarded to composite decorators</param>
 public override void DoPaintShape(RectangleD bounds, IGeometryHost shape, DiagramPaintEventArgs e)
 {
     if (myDecorators == null)
     {
         myDecorators = DecoratorCollection;
         if (myDecorators == null)
         {
             myDecorators = new LinkDecorator[] {};
         }
     }
     for (int i = myDecorators.Count - 1; i >= 0; --i)
     {
         myDecorators[i].DoPaintShape(bounds, shape, e);
     }
 }
Ejemplo n.º 7
0
		/// <summary>
		/// Paint the composite shape decorators. 
		/// </summary>
		/// <param name="bounds">Forwarded to composite decorators</param>
		/// <param name="shape">Forwarded to composite decorators</param>
		/// <param name="e">Forwarded to composite decorators</param>
		public override void DoPaintShape(RectangleD bounds, IGeometryHost shape, DiagramPaintEventArgs e)
		{
			if (myDecorators == null)
			{
				myDecorators = DecoratorCollection;
				if (myDecorators == null)
				{
					myDecorators = new LinkDecorator[]{};
				}
			}
			for (int i = myDecorators.Count - 1; i >= 0; --i)
			{
				myDecorators[i].DoPaintShape(bounds, shape, e);
			}
		}
Ejemplo n.º 8
0
            public override bool DoHitTest(IGeometryHost geometryHost, PointD hitPoint, DiagramHitTestInfo hitTestInfo,
                                           bool includeTolerance)
            {
                RectangleD perimeterBoundingBox = this.GetPerimeterBoundingBox(geometryHost);

                if (includeTolerance)
                {
                    perimeterBoundingBox.Inflate(ShapeGeometry.GetHitTestTolerance(hitTestInfo));
                }
                if (hitTestInfo != null)
                {
                    hitTestInfo.HitDiagramItem = null;
                    hitTestInfo.HitGrabHandle  = null;
                }

                // point is in the bounding rectangle
                bool flag = false;

                if (perimeterBoundingBox.Contains(hitPoint))
                {
                    // point is in the diamond shape
                    flag = isPointInTriangle(
                        new PointD(perimeterBoundingBox.X, perimeterBoundingBox.Y + perimeterBoundingBox.Height / 2),
                        new PointD(perimeterBoundingBox.X + perimeterBoundingBox.Width / 2, perimeterBoundingBox.Y),
                        new PointD(perimeterBoundingBox.X + perimeterBoundingBox.Width, perimeterBoundingBox.Y + perimeterBoundingBox.Height / 2),
                        hitPoint
                        );
                    if (!flag)
                    {
                        flag = isPointInTriangle(
                            new PointD(perimeterBoundingBox.X, perimeterBoundingBox.Y + perimeterBoundingBox.Height / 2),
                            new PointD(perimeterBoundingBox.X + perimeterBoundingBox.Width / 2, perimeterBoundingBox.Y + perimeterBoundingBox.Height),
                            new PointD(perimeterBoundingBox.X + perimeterBoundingBox.Width, perimeterBoundingBox.Y + perimeterBoundingBox.Height / 2),
                            hitPoint
                            );
                    }
                }

                if (flag && (hitTestInfo != null))
                {
                    hitTestInfo.HitDiagramItem = ShapeGeometry.CreateDiagramItem(geometryHost);
                }
                return(flag);
            }
Ejemplo n.º 9
0
            /*
             * the function return the 'anchor point' on the shape, lines of links will connect to the 'anchor point'
             *
             * potentialPoint is on the line which is crossing with the shape, and it's relative to (left, top) of the geometry
             * bounding box
             *
             * vectorEndpoint is a vector which defines the slope and direction of the line which is crossing with the shape
             *
             * the crossing point is the returned 'anchor point'
             *
             * the returned point is also relative to (left, top) of the geometry bounding box
             */
            public override PointD DoFoldToShape(IGeometryHost geometryHost, PointD potentialPoint, PointD vectorEndpoint)
            {
                RectangleD geometryBoundingBox = geometryHost.GeometryBoundingBox;

                PointD A = new PointD(0, geometryBoundingBox.Height / 2);
                PointD B = new PointD(geometryBoundingBox.Width / 2, 0);
                PointD C = new PointD(geometryBoundingBox.Width, geometryBoundingBox.Height / 2);
                PointD D = new PointD(geometryBoundingBox.Width / 2, geometryBoundingBox.Height);

                // corssing point
                PointD[] cp =
                {
                    getCrossPoint(A, B, potentialPoint, vectorEndpoint),
                    getCrossPoint(B, C, potentialPoint, vectorEndpoint),
                    getCrossPoint(C, D, potentialPoint, vectorEndpoint),
                    getCrossPoint(D, A, potentialPoint, vectorEndpoint)
                };

                double distance      = double.MaxValue;
                PointD crossingPoint = PointD.Empty;

                foreach (PointD pt in cp)
                {
                    if (pt.IsEmpty)
                    {
                        continue;
                    }
                    double dist = getPointDistance(potentialPoint, pt);
                    if (dist < distance)
                    {
                        distance      = dist;
                        crossingPoint = pt;
                    }
                }

                return(crossingPoint);
            }
Ejemplo n.º 10
0
		/// <summary>
		/// Locate the opposite shape based on the given points and
		/// adjust the opposite the endpoint accordingly. The endpoint
		/// is also modified to represent an absolute value. Use VectorEndPointForBase
		/// to restore the vector endpoint to its natural value.
		/// CenterToCenter routing is assumed.
		/// </summary>
		/// <param name="geometryHost">IGeometryHost (passed from DoFoldToShape)</param>
		/// <param name="vectorEndPoint">PointD (passed from DoFoldToShape)</param>
		/// <returns>Absolute location of end point</returns>
		public static PointD AdjustVectorEndPoint(IGeometryHost geometryHost, PointD vectorEndPoint)
		{
			NodeShape oppositeShape;
			return AdjustVectorEndPoint(geometryHost, vectorEndPoint, out oppositeShape);
		}
Ejemplo n.º 11
0
		/// <summary>
		/// Reimplementation of <see cref="LinkDecorator.DoPaintShape"/> that
		/// recognizes <see cref="IDynamicColorGeometryHost"/>
		/// </summary>
		public override void DoPaintShape(RectangleD bounds, IGeometryHost shape, DiagramPaintEventArgs e)
		{
			StyleSet styleSet = shape.GeometryStyleSet;
			GraphicsPath decoratorPath = GetPath(bounds);
			StyleSetResourceId penId = PenId;
			Pen pen = styleSet.GetPen(penId);
			StyleSetResourceId brushId = BrushId;
			Brush brush = styleSet.GetBrush(brushId);
			if (((decoratorPath != null) && (pen != null)) && (brush != null))
			{
				DiagramClientView clientView = e.View;
				IDynamicColorGeometryHost dynamicColors = shape as IDynamicColorGeometryHost;
				Graphics g = e.Graphics;
				Color restoreColor;
				if (FillDecorator)
				{
					restoreColor = Color.Empty;
					if (dynamicColors == null ||
						(restoreColor = dynamicColors.UpdateDynamicColor(brushId, brush)).IsEmpty)
					{
						if (clientView != null)
						{
							restoreColor = shape.UpdateGeometryLuminosity(clientView, brush);
						}
					}
					else if (clientView != null)
					{
						shape.UpdateGeometryLuminosity(clientView, brush);
					}
					g.FillPath(brush, decoratorPath);
					SolidBrush solidBrush;
					if (!restoreColor.IsEmpty &&
						null != (solidBrush = brush as SolidBrush))
					{
						solidBrush.Color = restoreColor;
					}
				}
				restoreColor = Color.Empty;
				if (dynamicColors == null ||
					(restoreColor = dynamicColors.UpdateDynamicColor(penId, pen)).IsEmpty)
				{
					if (clientView != null)
					{
						restoreColor = shape.UpdateGeometryLuminosity(clientView, pen);
					}
				}
				else if (clientView != null)
				{
					shape.UpdateGeometryLuminosity(clientView, pen);
				}
				GeometryUtility.SafeDrawPath(e.Graphics, pen, decoratorPath);
				if (!restoreColor.IsEmpty)
				{
					pen.Color = restoreColor;
				}
			}
		}
Ejemplo n.º 12
0
		/// <summary>
		/// Implements <see cref="IOffsetBorderPoint.OffsetBorderPoint"/>
		/// </summary>
		protected PointD? OffsetBorderPoint(IGeometryHost geometryHost, PointD borderPoint, PointD outsidePoint, double offset, bool parallelVector)
		{
			double angle = GeometryUtility.CalculateRadiansRotationAngle(outsidePoint, borderPoint);

			// Get the sample point
			PointD samplePoint = borderPoint;
			samplePoint.Offset(-offset * Math.Sin(angle), offset * Math.Cos(angle));

			// Figure out the slope, either parallel to the incoming line, or pointed at the outside point
			PointD slopeThrough = parallelVector ? borderPoint : samplePoint;

			// Translate the rectangle to the origin
			RectangleD bounds = geometryHost.GeometryBoundingBox;
			PointD hostCenter = bounds.Center;
			double hcx = hostCenter.X;
			double hcy = hostCenter.Y;
			samplePoint.Offset(-hcx, -hcy);
			borderPoint.Offset(-hcx, -hcy);

			double px = samplePoint.X;
			double py = samplePoint.Y;
			double solvedX;
			double solvedY;

			double halfWidth = bounds.Width / 2;
			double halfHeight = bounds.Height / 2;
			double r = Radius;
			if (VGConstants.FuzzEqual(slopeThrough.X, outsidePoint.X, VGConstants.FuzzDistance))
			{
				double absX = Math.Abs(px);
				// Vertical line, hit the same edge as the border point
				if (absX > (halfWidth + VGConstants.FuzzDistance))
				{
					// Line hits outside rectangle
					return null;
				}

				solvedX = px;
				solvedY = halfHeight;
				absX = halfWidth - absX;
				if (absX < r)
				{
					// We're on the rounded corner. Figure out how far down the circle we need to go.
					solvedY -= r - Math.Sqrt(absX * (r + r - absX));
				}
				if (borderPoint.Y < 0)
				{
					solvedY = -solvedY;
				}
			}
			else if (VGConstants.FuzzEqual(slopeThrough.Y, outsidePoint.Y, VGConstants.FuzzDistance))
			{
				double absY = Math.Abs(py);
				// Horizontal line, hit the same edge as the border point
				if (absY > (halfHeight + VGConstants.FuzzDistance))
				{
					// Line hits outside rectangle
					return null;
				}
				solvedY = py;
				solvedX = halfWidth;
				absY = halfHeight - absY;
				if (absY < r)
				{
					// We're on the rounded corner. Figure out how far down the circle we need to go.
					solvedX -= r - Math.Sqrt(absY * (r + r - absY));
				}
				if (borderPoint.X < 0)
				{
					solvedX = -solvedX;
				}
			}
			else
			{
				int hitCount = 0;
				solvedX = 0;
				solvedY = 0;
				double solvedXAlternate = 0;
				double solvedYAlternate = 0;
				PointD? corner; // Use for corner tracking (both the center and the hit points)
				CornerQuadrant quadrant = 0;

				// We've already checked vertical and horizontal lines, so we know the lines will intersect either
				// zero or two sides of the rectangle. Find the two sides.
				// The intersecting line equation is y = m(x - px) + py (solved for y) or x = 1/m(y-py) + px (solved for x)
				// The rectangle borders are y = halfHeight, y = -halfHeight, x = halfWidth, x = -halfWidth
				double slope = (outsidePoint.Y - slopeThrough.Y) / (outsidePoint.X - slopeThrough.X);
				double inverseSlope = 1 / slope;

				double testIntersect;

				// Bottom edge
				testIntersect = inverseSlope * (halfHeight - py) + px;
				if (Math.Abs(testIntersect) < (halfWidth + VGConstants.FuzzDistance))
				{
					solvedX = testIntersect;
					solvedY = halfHeight;
					corner = null;
					if (solvedX > 0)
					{
						if (r > (halfWidth - solvedX))
						{
							corner = new PointD(halfWidth - r, halfHeight - r);
							quadrant = CornerQuadrant.LowerRight;
						}
					}
					else if (r > (halfWidth + solvedX))
					{
						corner = new PointD(-halfWidth + r, halfHeight - r);
						quadrant = CornerQuadrant.LowerLeft;
					}

					if (corner.HasValue)
					{
						corner = FindCornerHit(corner.Value, samplePoint, slope, r, quadrant);
						if (!corner.HasValue)
						{
							return null;
						}
						solvedX = corner.Value.X;
						solvedY = corner.Value.Y;
					}
					hitCount = 1;
				}

				// Top edge
				testIntersect = inverseSlope * (-halfHeight - py) + px;
				if (Math.Abs(testIntersect) < (halfWidth + VGConstants.FuzzDistance))
				{
					solvedXAlternate = testIntersect;
					solvedYAlternate = -halfHeight;
					corner = null;
					if (solvedXAlternate > 0)
					{
						if (r > (halfWidth - solvedXAlternate))
						{
							corner = new PointD(halfWidth - r, -halfHeight + r);
							quadrant = CornerQuadrant.UpperRight;
						}
					}
					else if (r > (halfWidth + solvedXAlternate))
					{
						corner = new PointD(-halfWidth + r, -halfHeight + r);
						quadrant = CornerQuadrant.UpperLeft;
					}
					if (corner.HasValue)
					{
						corner = FindCornerHit(corner.Value, samplePoint, slope, r, quadrant);
						if (!corner.HasValue)
						{
							return null;
						}
						solvedXAlternate = corner.Value.X;
						solvedYAlternate = corner.Value.Y;
					}
					if (hitCount == 0)
					{
						solvedX = solvedXAlternate;
						solvedY = solvedYAlternate;
					}
					++hitCount;
				}

				// Right edge
				if (hitCount != 2)
				{
					testIntersect = slope * (halfWidth - px) + py;
					if (Math.Abs(testIntersect) < (halfHeight + VGConstants.FuzzDistance))
					{
						solvedYAlternate = testIntersect;
						solvedXAlternate = halfWidth;
						corner = null;
						if (solvedYAlternate > 0)
						{
							if (r > (halfHeight - solvedYAlternate))
							{
								corner = new PointD(halfWidth - r, halfHeight - r);
								quadrant = CornerQuadrant.LowerRight;
							}
						}
						else if (r > (halfHeight + solvedYAlternate))
						{
							corner = new PointD(halfWidth - r, -halfHeight + r);
							quadrant = CornerQuadrant.UpperRight;
						}
						if (corner.HasValue)
						{
							corner = FindCornerHit(corner.Value, samplePoint, slope, r, quadrant);
							if (!corner.HasValue)
							{
								return null;
							}
							solvedXAlternate = corner.Value.X;
							solvedYAlternate = corner.Value.Y;
						}
						if (hitCount == 0)
						{
							solvedX = solvedXAlternate;
							solvedY = solvedYAlternate;
						}
						++hitCount;
					}
				}

				// Left edge
				if (hitCount == 1)
				{
					testIntersect = slope * (-halfWidth - px) + py;
					if (Math.Abs(testIntersect) < (halfHeight + VGConstants.FuzzDistance))
					{
						solvedYAlternate = testIntersect;
						solvedXAlternate = -halfWidth;
						corner = null;
						if (solvedYAlternate > 0)
						{
							if (r > (halfHeight - solvedYAlternate))
							{
								corner = new PointD(-halfWidth + r, halfHeight - r);
								quadrant = CornerQuadrant.LowerLeft;
							}
						}
						else if (r > (halfHeight + solvedYAlternate))
						{
							corner = new PointD(-halfWidth + r, -halfHeight + r);
							quadrant = CornerQuadrant.UpperLeft;
						}
						if (corner.HasValue)
						{
							corner = FindCornerHit(corner.Value, samplePoint, slope, r, quadrant);
							if (!corner.HasValue)
							{
								return null;
							}
							solvedXAlternate = corner.Value.X;
							solvedYAlternate = corner.Value.Y;
						}
						++hitCount;
					}
				}

				// Choose the best match and translate the point back out
				if (hitCount == 2)
				{
					// Find the point closest to the sample point
					double xDif = px - solvedX;
					double yDif = py - solvedY;
					double xDifAlternate = px - solvedXAlternate;
					double yDifAlternate = py - solvedYAlternate;
					if ((xDif * xDif + yDif * yDif) > (xDifAlternate * xDifAlternate + yDifAlternate * yDifAlternate))
					{
						solvedX = solvedXAlternate;
						solvedY = solvedYAlternate;
					}
				}
				else
				{
					// Unsolvable
					return null;
				}
			}
			return new PointD(solvedX + hcx, solvedY + hcy);
		}
Ejemplo n.º 13
0
        /// <summary>
        /// Replacement for LinkShapeGeometry.DrawDecorator
        /// </summary>
#if VISUALSTUDIO_10_0
        protected static new void DrawDecorator(DiagramPaintEventArgs e, IGeometryHost geometryHost, float rotation, PointD centerRight, LinkDecorator decorator, SizeD size)
        {
Ejemplo n.º 14
0
		/// <summary>
		/// A utility function to attempt to perfom custom shape folding.
		/// Custom shape folding uses shape-specific information beyond that
		/// available to the ShapeGeometry to determine connection points.
		/// This function should be call after AdjustVectorEndPoint.
		/// </summary>
		/// <param name="geometryHost">The geometryHost value passed to DoFoldToShape</param>
		/// <param name="vectorEndPoint">The vectorEndPoint passed to DoFoldToShape and adjusted by <see cref="AdjustVectorEndPoint(IGeometryHost,PointD,out NodeShape)"/></param>
		/// <param name="oppositeShape">The opposite shape returned by <see cref="AdjustVectorEndPoint(IGeometryHost,PointD,out NodeShape)"/></param>
		/// <returns>Nullable&lt;PointD&gt; with a value on success, without a value if custom folding is not available</returns>
		public static PointD? DoCustomFoldShape(IGeometryHost geometryHost, PointD vectorEndPoint, NodeShape oppositeShape)
		{
			ICustomShapeFolding customFolding;
			IProxyConnectorShape proxyConnector;
			PointD customPoint;
			NodeShape realHost;
			if (oppositeShape != null &&
				null != (customFolding = geometryHost as ICustomShapeFolding) &&
				!(customPoint = customFolding.CalculateConnectionPoint(oppositeShape)).IsEmpty)
			{
				// Translate back to local coordinates
				PointD location = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox).Location;
				customPoint.Offset(-location.X, -location.Y);
				return customPoint;
			}
			else if (null != (proxyConnector = geometryHost as IProxyConnectorShape) &&
				null != (realHost = proxyConnector.ProxyConnectorShapeFor as NodeShape))
			{
				SizeD size = realHost.Size;
				customPoint = realHost.ShapeGeometry.DoFoldToShape(new GeometryHostWrapper(realHost), new PointD(size.Width / 2, size.Height / 2), GeometryUtility.VectorEndPointForBase(realHost, vectorEndPoint));
				PointD location = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox).Location;
				PointD realLocation = realHost.AbsoluteBounds.Location;
				customPoint.Offset(realLocation.X - location.X, realLocation.Y - location.Y);
				return customPoint;
			}
			return null;
		}
Ejemplo n.º 15
0
		/// <summary>
		/// Locate the opposite shape based on the given points and
		/// adjust the opposite the endpoint accordingly. The endpoint
		/// is also modified to represent an absolute value. Use VectorEndPointForBase
		/// to restore the vector endpoint to its natural value.
		/// CenterToCenter routing is assumed.
		/// </summary>
		/// <param name="geometryHost">IGeometryHost (passed from DoFoldToShape)</param>
		/// <param name="vectorEndPoint">PointD (passed from DoFoldToShape)</param>
		/// <param name="oppositeShape">The located opposite shape at this location</param>
		/// <returns>Absolute location of end point</returns>
		public static PointD AdjustVectorEndPoint(IGeometryHost geometryHost, PointD vectorEndPoint, out NodeShape oppositeShape)
		{
			oppositeShape = null;
			// The vectorEndPoint value is coming in (negative, negative) for the lower
			// right quadrant instead of (positive, positive). All other values are
			// (positive, positive), so we switch the end point to make the rest of the work
			// easier. For CenterToCenter routing, subtracting the vectorEndPoint from the
			// lower right corner gives the correct value.
			RectangleD absoluteBoundingBox = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
#if VISUALSTUDIO_10_0
			PointD absoluteCenter = absoluteBoundingBox.Center;
			vectorEndPoint = new PointD(absoluteCenter.X - vectorEndPoint.X, absoluteCenter.Y - vectorEndPoint.Y);
#else
			vectorEndPoint = new PointD(absoluteBoundingBox.Right - vectorEndPoint.X, absoluteBoundingBox.Bottom - vectorEndPoint.Y);
#endif

			NodeShape shape = geometryHost as NodeShape;
			if (shape != null)
			{
				ReadOnlyCollection<LinkConnectsToNode> links = DomainRoleInfo.GetElementLinks<LinkConnectsToNode>(shape, LinkConnectsToNode.NodesDomainRoleId);
				int linksCount = links.Count;
				for (int i = 0; i < linksCount; ++i)
				{
					LinkConnectsToNode link = links[i];
					BinaryLinkShape linkShape = link.Link as BinaryLinkShape;
					if (link != null)
					{
						// Get the opposite shape
						NodeShape testShape;
						if (linkShape.FromLinkConnectsToNode == link)
						{
							testShape = linkShape.ToShape;
						}
						else
						{
							testShape = linkShape.FromShape;
						}

						PointD shapeCenter = testShape.AbsoluteCenter;
						if (VGConstants.FuzzEqual(shapeCenter.X, vectorEndPoint.X, VGConstants.FuzzDistance) &&
							VGConstants.FuzzEqual(shapeCenter.Y, vectorEndPoint.Y, VGConstants.FuzzDistance))
						{
							oppositeShape = testShape;
							ICustomShapeFolding customFolding = testShape as ICustomShapeFolding;
							if (customFolding != null)
							{
								PointD customEndPoint = customFolding.CalculateConnectionPoint(shape);
								if (!customEndPoint.IsEmpty)
								{
									vectorEndPoint = customEndPoint;
								}
							}
							break;
						}
					}
				}
			}
			return vectorEndPoint;
		}
Ejemplo n.º 16
0
		/// <summary>
		/// Implement shape folding on the triangle boundary
		/// </summary>
		/// <param name="geometryHost">The host view</param>
		/// <param name="potentialPoint">A point on the rectangular boundary of the shape</param>
		/// <param name="vectorEndPoint">A point on the opposite end of the connecting line</param>
		/// <returns>A point on the triangular border</returns>
		public override PointD DoFoldToShape(IGeometryHost geometryHost, PointD potentialPoint, PointD vectorEndPoint)
		{
			// Get an endpoint we can work with
			NodeShape oppositeShape;
			vectorEndPoint = GeometryUtility.AdjustVectorEndPoint(geometryHost, vectorEndPoint, out oppositeShape);
			PointD? customPoint = GeometryUtility.DoCustomFoldShape(geometryHost, vectorEndPoint, oppositeShape);
			if (customPoint.HasValue)
			{
				return customPoint.Value;
			}
			vectorEndPoint = GeometryUtility.ResolveProxyConnectorVectorEndPoint(vectorEndPoint, oppositeShape);
			RectangleD bounds = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
			PointD center = bounds.Center;
			PointD[] trianglePoints = GeometryUtility.GetTrianglePointsD(bounds);
			double offsetByX = -center.X;
			double offsetByY = -center.Y;
			for (int i = 0; i < trianglePoints.Length; ++i)
			{
				trianglePoints[i].Offset(offsetByX, offsetByY);
			}
			vectorEndPoint.Offset(offsetByX, offsetByY);
			bool negativeX = vectorEndPoint.X < 0;
			bool negativeY = vectorEndPoint.Y < 0;
			double halfWidth = bounds.Width / 2;
			double halfHeight = bounds.Height / 2;

			if (VGConstants.FuzzZero(vectorEndPoint.X, VGConstants.FuzzDistance))
			{
				// Vertical line, skip slope calculations
				return new PointD(halfWidth, trianglePoints[negativeY ? 0 : 1].Y + halfHeight);
			}
			else if (VGConstants.FuzzZero(vectorEndPoint.Y, VGConstants.FuzzDistance))
			{
				// Horizontal line, skip slope calculations
				// Solve two-point form of line between triangle points for x with y = 0.
				PointD topPoint = trianglePoints[0];
				PointD bottomPoint = trianglePoints[negativeX ? 1 : 2];
				return new PointD(topPoint.X - topPoint.Y * (bottomPoint.X - topPoint.X)/(bottomPoint.Y - topPoint.Y) + halfWidth, halfHeight);
			}
			else
			{
				double slope = vectorEndPoint.Y / vectorEndPoint.X;
				double x;
				double y;
				if (negativeY || (Math.Abs(slope) < (halfHeight / halfWidth))) // Reasonable, but allows y to spill below the bottom
				{
					// Try to attach to the left/right lines
					PointD topPoint = trianglePoints[0];
					PointD bottomPoint = trianglePoints[negativeX ? 1 : 2];
					double inverseTriangleSlope = (bottomPoint.X - topPoint.X) / (bottomPoint.Y - topPoint.Y);
					x = (topPoint.X - topPoint.Y * inverseTriangleSlope) / (1 - slope * inverseTriangleSlope);
					y = slope * x;
					if (y > bottomPoint.Y)
					{
						// Adjust for a y below the bottom point.
						y = bottomPoint.Y;
						x = y / slope;
					}
				}
				else
				{
					// Attach to the bottom edge
					y = trianglePoints[1].Y;
					x = y / slope;
				}
				return new PointD(x + halfWidth, y + halfHeight);
			}
		}
Ejemplo n.º 17
0
            /// <summary>
            /// Paint the solid crowsfoot on the end of an optional line
            /// </summary>
            protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
            {
                AssociationConnector connector = (AssociationConnector)geometryHost;
                BarkerErModelContainsBinaryAssociation link = connector.ModelElement as BarkerErModelContainsBinaryAssociation;

                EdgePointCollection edgePoints;
                int edgePointCount;
                BinaryAssociation association;
                LinkedElementCollection <Barker.Role> roles;

                if (null != (edgePoints = connector.EdgePoints) &&
                    1 < (edgePointCount = edgePoints.Count) &&
                    null != (association = link.BinaryAssociation) &&
                    2 == (roles = association.RoleCollection).Count)
                {
                    PointD p1   = edgePoints[edgePointCount - 1].Point;
                    PointD p2   = edgePoints[0].Point;
                    PointD midP = new PointD((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);

                    #region find correct roles
                    EntityType  fromEntity = connector.FromShape.ModelElement as EntityType;
                    EntityType  toEntity = connector.ToShape.ModelElement as EntityType;
                    Barker.Role fromRole = null, toRole = null;
                    if (fromEntity == roles[0].EntityType)
                    {
                        fromRole = roles[0];
                    }
                    else if (fromEntity == roles[1].EntityType)
                    {
                        fromRole = roles[1];
                    }
                    if (toEntity == roles[0].EntityType)
                    {
                        toRole = roles[0];
                    }
                    else if (toEntity == roles[1].EntityType)
                    {
                        toRole = roles[1];
                    }
                    #endregion

                    if (fromRole != null && toRole != null)
                    {
                        bool fromOptional = !fromRole.IsMandatory;
                        bool toOptional   = !toRole.IsMandatory;
                        bool bothOptional = fromOptional && toOptional;

                        PointF?v1 = null, v2 = null;
                        DrawAssociationEnd(
                            e, geometryHost, connector.FromShape, p2, midP, fromRole.IsMultiValued, fromOptional, fromRole.IsPrimaryIdComponent,
                            fromRole.PredicateText, ref v1, bothOptional);
                        DrawAssociationEnd(
                            e, geometryHost, connector.ToShape, p1, midP, toRole.IsMultiValued, toOptional, toRole.IsPrimaryIdComponent,
                            toRole.PredicateText, ref v2, bothOptional);

                        if (bothOptional && v1.HasValue && v2.HasValue)
                        {
                            Pen pen = geometryHost.GeometryStyleSet.GetPen(DiagramPens.ConnectionLine);
                            pen             = (Pen)pen.Clone();
                            pen.DashPattern = DashPattern;
                            e.Graphics.DrawLine(pen, v1.Value, v2.Value);
                        }
                    }
                }
            }
Ejemplo n.º 18
0
		/// <summary>
		/// Replacement for <see cref="NodeShapeGeometry.DoPaintGeometry"/> that supports
		/// dynamic background and outline colors.
		/// </summary>
		protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
		{
			IDynamicColorGeometryHost dynamicColors = geometryHost as IDynamicColorGeometryHost;
			if (dynamicColors != null)
			{
				GeometryUtility.PaintDynamicColorGeometry(e, geometryHost, dynamicColors, this, this.HasFilledBackground(geometryHost), this.HasOutline(geometryHost));
			}
			else
			{
				base.DoPaintGeometry(e, geometryHost);
			}
		}
Ejemplo n.º 19
0
		/// <summary>
		/// Implement shape folding on the ellipse boundary
		/// </summary>
		/// <param name="geometryHost">The host view</param>
		/// <param name="potentialPoint">A point on the rectangular boundary of the shape</param>
		/// <param name="vectorEndPoint">A point on the opposite end of the connecting line</param>
		/// <returns>A point on the ellipse border</returns>
		public override PointD DoFoldToShape(IGeometryHost geometryHost, PointD potentialPoint, PointD vectorEndPoint)
		{
			// Get an endpoint we can work with
			NodeShape oppositeShape;
			vectorEndPoint = GeometryUtility.AdjustVectorEndPoint(geometryHost, vectorEndPoint, out oppositeShape);
			PointD? customPoint = GeometryUtility.DoCustomFoldShape(geometryHost, vectorEndPoint, oppositeShape);
			if (customPoint.HasValue)
			{
				return customPoint.Value;
			}
			vectorEndPoint = GeometryUtility.ResolveProxyConnectorVectorEndPoint(vectorEndPoint, oppositeShape);

			// The point returned needs to be relative to the upper left corner of the bounding
			// box. The goal is to get a point on the circle that points to the center of the
			// line. To do this, we translate the coordinate system to the center of the circle,
			// get a slope from the vectorEndPoint/circle center, then solve the circle equation
			// and retranslate the coordinates back out.
			// The quadrant we're coming in from can be determined by the position of the vectorEndPoint
			// relative to the ellipse center.
			//
			// The pertinent equations are:
			// vectorEndPoint (relative point) = (xe, ye)
			// center = (xc, yc)
			// circle radius = r
			// slope = m = (ye - yc)/(xe - xc)
			// line equation: y = mx
			// circle equation (centered at origin): x^2 + y^2 = r^2
			// solving gives us: x = +/-(r/sqrt(1 + m^2))
			// Plugging back into the line equation gives us a +/- y value
			// Final point = (xc, yc) + (x, y)
			// The quadrant is determined by the relative position of the vectorEndPoint
			RectangleD box = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
			PointD boxCenter = box.Center;
			double radius = Math.Min(box.Width / 2, box.Height / 2);

			if (VGConstants.FuzzEqual(vectorEndPoint.X, boxCenter.X, VGConstants.FuzzDistance))
			{
				return new PointD(box.Width / 2, (vectorEndPoint.Y < boxCenter.Y) ? 0 : box.Height);
			}
			else if (VGConstants.FuzzEqual(vectorEndPoint.Y, boxCenter.Y, VGConstants.FuzzDistance))
			{
				return new PointD((vectorEndPoint.X < boxCenter.X) ? 0 : box.Width, box.Height / 2);
			}
			else
			{
				bool negativeX = vectorEndPoint.X < boxCenter.X;
				bool negativeY = vectorEndPoint.Y < boxCenter.Y;

				double slope = (vectorEndPoint.Y - boxCenter.Y) / (vectorEndPoint.X - boxCenter.X);
				double x = radius / Math.Sqrt(1 + slope * slope);
				double y = slope * x;
				x = Math.Abs(x);
				y = Math.Abs(y);
				if (negativeX)
				{
					x = -x;
					if (negativeY)
					{
						y = -y;
					}
				}
				else if (negativeY)
				{
					y = -y;
				}
				// Return a point relative to the shape
				return new PointD(x + radius, y + radius);
			}
		}
Ejemplo n.º 20
0
		PointD? IOffsetBorderPoint.OffsetBorderPoint(IGeometryHost geometryHost, PointD borderPoint, PointD outsidePoint, double offset, bool parallelVector)
		{
			return OffsetBorderPoint(geometryHost, borderPoint, outsidePoint, offset, parallelVector);
		}
Ejemplo n.º 21
0
		/// <summary>
		/// Implements <see cref="IOffsetBorderPoint.OffsetBorderPoint"/>
		/// </summary>
		protected PointD? OffsetBorderPoint(IGeometryHost geometryHost, PointD borderPoint, PointD outsidePoint, double offset, bool parallelVector)
		{
			double angle = GeometryUtility.CalculateRadiansRotationAngle(outsidePoint, borderPoint);

			// Get the sample point
			PointD samplePoint = borderPoint;
			samplePoint.Offset(-offset * Math.Sin(angle), offset * Math.Cos(angle));

			// Figure out the slope, either parallel to the incoming line, or pointed at the outside point
			PointD slopeThrough = parallelVector ? borderPoint : samplePoint;

			// Translate the ellipse to the origin
			RectangleD bounds = geometryHost.GeometryBoundingBox;
			PointD hostCenter = bounds.Center;
			samplePoint.Offset(-hostCenter.X, -hostCenter.Y);

			double px = samplePoint.X;
			double py = samplePoint.Y;
			double solvedX;
			double solvedY;
			bool checkAlternate = false;
			double solvedXAlternate = 0;
			double solvedYAlternate = 0;

			if (VGConstants.FuzzEqual(slopeThrough.X, outsidePoint.X, VGConstants.FuzzDistance))
			{
				// Vertical line, can't get slope, y = +/-b * sqrt(1-(x0/a)^2)
				double discriminant = px / (bounds.Width / 2);
				discriminant = 1 - discriminant * discriminant;
				if (VGConstants.FuzzZero(discriminant, VGConstants.FuzzGeneral))
				{
					solvedX = px;
					solvedY = 0;
				}
				else if (discriminant < 0)
				{
					// Equation is not solvable
					return null;
				}
				else
				{
					solvedX = px;
					solvedY = (bounds.Height / 2) * Math.Sqrt(discriminant);
					solvedXAlternate = px;
					solvedYAlternate = -solvedY;
					checkAlternate = true;
				}
			}
			else if (VGConstants.FuzzEqual(slopeThrough.Y, outsidePoint.Y, VGConstants.FuzzDistance))
			{
				// Horizontal line, main equation works, but this is a lot cleaner.
				// Switch axes from vertical block
				double discriminant = py / (bounds.Height / 2);
				discriminant = 1 - discriminant * discriminant;
				if (VGConstants.FuzzZero(discriminant, VGConstants.FuzzGeneral))
				{
					solvedY = py;
					solvedX = 0;
				}
				else if (discriminant < 0)
				{
					// Equation is not solvable
					return null;
				}
				else
				{
					solvedY = py;
					solvedX = (bounds.Width / 2) * Math.Sqrt(discriminant);
					solvedYAlternate = py;
					solvedXAlternate = -solvedX;
					checkAlternate = true;
				}
			}
			else
			{
				double slope = (outsidePoint.Y - slopeThrough.Y) / (outsidePoint.X - slopeThrough.X);
				double xRadiusSquared = bounds.Width / 2;
				xRadiusSquared *= xRadiusSquared;
				double yRadiusSquared = bounds.Height / 2;
				yRadiusSquared *= yRadiusSquared;
				// The A/B/C below refer to the quadratic equation (Ax^2 + Bx + C = 0) gives
				// The equations involved are
				// Ellipse equation: x^2/a^2 + y^2/b^2 = 1 for the ellipse (a = width/2, b = height/2, centered at 0,0)
				// Line equation: x = m(x - x0) + y0 (m = slope, x0 = px above, y0 = py above). Solving into
				// quadratic form gives the following equations:
				double quadA = yRadiusSquared / xRadiusSquared + slope * slope;
				double sharedQuadPart = py - slope * px;
				double quadB = (slope + slope) * sharedQuadPart;
				double quadC = sharedQuadPart * sharedQuadPart - yRadiusSquared;
				double discriminant = quadB * quadB - 4 * quadA * quadC;
				if (VGConstants.FuzzZero(discriminant, VGConstants.FuzzGeneral))
				{
					// Tangential line, one possibility only
					solvedX = -quadB / (quadA + quadA);
					solvedY = slope * (solvedX - px) + py;
				}
				else if (discriminant < 0)
				{
					// Equation is not solvable
					return null;
				}
				else
				{
					// We want the point that is closest to the sample point.
					discriminant = Math.Sqrt(discriminant);
					solvedX = (-quadB + discriminant) / (quadA + quadA);
					solvedY = slope * (solvedX - px) + py;
					solvedXAlternate = (-quadB - discriminant) / (quadA + quadA);
					solvedYAlternate = slope * (solvedXAlternate - px) + py;
					checkAlternate = true;
				}
			}

			// Choose the best match and translate the point back out
			if (checkAlternate)
			{
				// Note that simple quadrant checks are no sufficient here, we must
				// find the closest solution to the starting point
				double xDif = px - solvedX;
				double yDif = py - solvedY;
				double xDifAlternate = px - solvedXAlternate;
				double yDifAlternate = py - solvedYAlternate;
				if ((xDif * xDif + yDif * yDif) > (xDifAlternate * xDifAlternate + yDifAlternate * yDifAlternate))
				{
					solvedX = solvedXAlternate;
					solvedY = solvedYAlternate;
				}
			}
			return new PointD(solvedX + hostCenter.X, solvedY + hostCenter.Y);
		}
Ejemplo n.º 22
0
		/// <summary>
		/// Paint the background and outline of a <see cref="IGeometryHost"/> using
		/// dynamic colors provided by the <see cref="IDynamicColorGeometryHost"/> interface.
		/// This is a helper method designed to be called by an override of the <see cref="NodeShapeGeometry.DoPaintGeometry"/> method.
		/// </summary>
		/// <param name="e">The <see cref="DiagramPaintEventArgs"/> passed to DoPaintGeometry</param>
		/// <param name="geometryHost">The <see cref="IGeometryHost"/> passed to DoPaintGeometry</param>
		/// <param name="dynamicColors">The <see cref="IDynamicColorGeometryHost"/> retrieved from the <paramref name="geometryHost"/></param>
		/// <param name="shapeGeometry">The <see cref="ShapeGeometry"/> this is a helper for.</param>
		/// <param name="hasFilledBackground">The result of the <see cref="ShapeGeometry.HasFilledBackground"/> method</param>
		/// <param name="hasOutline">The result of the <see cref="ShapeGeometry.HasOutline"/> method</param>
		/// <remarks>
		/// The DoPaintGeometry override should look similar to
		/// <code>
		/// protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
		/// {
		///     IDynamicColorGeometryHost dynamicColors = geometryHost as IDynamicColorGeometryHost;
		///     if (dynamicColors != null)
		///     {
		///         GeometryUtility.PaintDynamicColorGeometry(e, geometryHost, dynamicColors, this, this.HasFilledBackground(geometryHost), this.HasOutline(geometryHost));
		///     }
		///     else
		///     {
		///         base.DoPaintGeometry(e, geometryHost);
		///     }
		/// }
		/// </code>
		/// </remarks>
		public static void PaintDynamicColorGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost, IDynamicColorGeometryHost dynamicColors, ShapeGeometry shapeGeometry, bool hasFilledBackground, bool hasOutline)
		{
			if (hasFilledBackground || hasOutline)
			{
				StyleSet geometryStyleSet = geometryHost.GeometryStyleSet;
				GraphicsPath path;
				StyleSetResourceId penId = null;
				Pen pen = null;
				StyleSetResourceId brushId = null;
				Brush brush = null;
				if (null != (path = shapeGeometry.GetPath(geometryHost)) &&
					(!hasFilledBackground || null != (brush = geometryStyleSet.GetBrush(brushId = shapeGeometry.GetBackgroundBrushId(geometryHost)))) &&
					(!hasOutline || null != (pen = geometryStyleSet.GetPen(penId = shapeGeometry.GetOutlinePenId(geometryHost)))))
				{
					Graphics g = e.Graphics;
					DiagramClientView clientView = e.View;
					Color restoreColor;
					if (brush != null)
					{
						restoreColor = Color.Empty;
						if (dynamicColors == null ||
							(restoreColor = dynamicColors.UpdateDynamicColor(brushId, brush)).IsEmpty)
						{
							if (clientView != null)
							{
								restoreColor = geometryHost.UpdateGeometryLuminosity(clientView, brush);
							}
						}
						else if (clientView != null)
						{
							geometryHost.UpdateGeometryLuminosity(clientView, brush);
						}
						g.FillPath(brush, path);
						SolidBrush solidBrush = brush as SolidBrush;
						if (!restoreColor.IsEmpty &&
							null != (solidBrush = brush as SolidBrush))
						{
							solidBrush.Color = restoreColor;
						}
					}
					if (pen != null)
					{
						restoreColor = Color.Empty;
						if (dynamicColors == null ||
							(restoreColor = dynamicColors.UpdateDynamicColor(penId, pen)).IsEmpty)
						{
							if (clientView != null)
							{
								restoreColor = geometryHost.UpdateGeometryLuminosity(clientView, pen);
							}
						}
						else if (clientView != null)
						{
							geometryHost.UpdateGeometryLuminosity(clientView, pen);
						}
						SafeDrawPath(g, pen, path);
						if (!restoreColor.IsEmpty)
						{
							pen.Color = restoreColor;
						}
					}
				}
			}
		}
		/// <summary>
		/// Override of DoHitTest so it works with non-rectilinear line segments
		/// </summary>
		public override bool DoHitTest(IGeometryHost geometryHost, PointD hitPoint, DiagramHitTestInfo hitTestInfo, bool includeTolerance)
		{
			bool retVal = false;
			LineSegment hitSegment = null;
			AnchorPoint anchorPoint = null;
			// In DSL Tools v8.2, GetHitTestTolerance is an instance method, but in DSL Tools v9.0, it is a static method.
			// We call it without a qualifier here so that it will compile against both versions.
			SizeD tolerance = GetHitTestTolerance(hitTestInfo);
			RectangleD perimeter = this.GetPerimeterBoundingBox(geometryHost);
			perimeter.Inflate(tolerance);
			if (perimeter.Contains(hitPoint))
			{
				LineSegment[] segments = this.CalculateSegments(geometryHost, hitTestInfo);
				int segmentCount = segments.Length;
				for (int i = 0; i < segmentCount; ++i)
				{
					LineSegment testSegment = segments[i];
					RectangleD testBounds = GeometryHelpers.RectangleDFrom2Pts(testSegment.StartPoint, testSegment.EndPoint);
					testBounds.Inflate(tolerance);
					if (testBounds.Contains(hitPoint))
					{
						anchorPoint = TestHitAnchor(geometryHost as BinaryLinkShape, testSegment, tolerance, hitPoint);
						if (anchorPoint != null)
						{
							retVal = true;
							hitSegment = testSegment;
							break;
						}
						double distance = DistanceFromPointToLine(hitPoint, testSegment.StartPoint, testSegment.EndPoint, true);
						if (!double.IsNaN(distance) && distance < (tolerance.Width + geometryHost.GeometryStyleSet.GetPen(geometryHost.GeometryOutlinePenId).Width / 2f))
						{
							retVal = true;
							hitSegment = testSegment;
							break;
						}
					}
				}
			}
			if (hitTestInfo != null)
			{
				DiagramItem diagramItem;
				if (retVal)
				{
					if (anchorPoint == null)
					{
						// In DSL Tools v8.2, CreateDiagramItem is an instance method, but in DSL Tools v9.0, it is a static method.
						// We call it without a qualifier here so that it will compile against both versions.
						diagramItem = CreateDiagramItem(geometryHost, hitSegment);
					}
					else
					{
						diagramItem = new DiagramItem(geometryHost as LinkShape, hitSegment, anchorPoint);
					}
				}
				else
				{
					diagramItem = null;
				}
				hitTestInfo.HitDiagramItem = diagramItem;
				hitTestInfo.HitGrabHandle = null;
			}
			return retVal;
		}
		/// <summary>
		/// Pulled directly from Reflector disassembly
		/// </summary>
		private LineSegment[] CalculateSegments(IGeometryHost geometryHost, DiagramHitTestInfo hitTestInfo)
		{
			IBinaryLinkGeometryData data1 = geometryHost as IBinaryLinkGeometryData;
			EdgePointCollection collection1 = data1.GeometryEdgePointsNoJumps;
			LineSegment[] segmentArray1 = new LineSegment[collection1.Count - 1];
			Pen pen1 = geometryHost.GeometryStyleSet.GetPen(this.GetOutlinePenId(geometryHost));
			if (pen1 != null)
			{
				for (int num1 = 0; num1 < (collection1.Count - 1); num1++)
				{
					RectangleD ed1 = GeometryHelpers.RectangleDFrom2Pts(collection1[num1].Point, collection1[num1 + 1].Point);
					// In DSL Tools v8.2, GetHitTestTolerance is an instance method, but in DSL Tools v9.0, it is a static method.
					// We call it without a qualifier here so that it will compile against both versions.
					SizeD ed2 = GetHitTestTolerance(hitTestInfo);
					if (ed1.Height < ed2.Height)
					{
						ed1.Inflate(0, (pen1.Width / 2f) + ed2.Height);
					}
					else if (ed1.Width < ed2.Width)
					{
						ed1.Inflate((pen1.Width / 2f) + ed2.Width, 0);
					}
					segmentArray1[num1] = new LineSegment(collection1[num1].Point, collection1[num1 + 1].Point, num1, num1 + 1, num1 == 0, (num1 + 1) == (collection1.Count - 1), ed1);
				}
			}
			return segmentArray1;
		}
Ejemplo n.º 25
0
		/// <summary>
		/// Adjust a vector end point retrieved from AdjustVectorEndPoint into
		/// the value in its original (very strange) coordinate system.
		/// </summary>
		/// <param name="geometryHost">The geometryHost passed to FoldToShape</param>
		/// <param name="vectorEndPoint">An adjusted vector end point</param>
		/// <returns>An unadjusted value</returns>
		public static PointD VectorEndPointForBase(IGeometryHost geometryHost, PointD vectorEndPoint)
		{
			RectangleD absoluteBoundingBox = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
#if VISUALSTUDIO_10_0
			PointD absoluteCenter = absoluteBoundingBox.Center;
			return new PointD(absoluteCenter.X - vectorEndPoint.X, absoluteCenter.X - vectorEndPoint.Y);
#else
			return new PointD(absoluteBoundingBox.Right - vectorEndPoint.X, absoluteBoundingBox.Bottom - vectorEndPoint.Y);
#endif
		}
Ejemplo n.º 26
0
        /// <summary>
        /// Draws the shape's shadow.
        /// </summary>
        /// <remarks>
        /// The shadow is replaced with a glow.
        /// </remarks>
        protected override void DoPaintShadow(DiagramPaintEventArgs e, IGeometryHost geometryHost)
        {
            Guard.NotNull(() => geometryHost, geometryHost);
            Guard.NotNull(() => e, e);

            Graphics      graphics     = e.Graphics;
            GraphicsState state        = graphics.Save();
            SizeD         shadowOffset = this.ShadowOffset;

            try
            {
                GraphicsPath shapePath      = this.GetPath(geometryHost);
                RectangleF   shapeRectangle = shapePath.GetBounds();

                // Create shadow path
                GraphicsPath shadowPath = shapePath.Clone() as GraphicsPath;

                // Enlarge the shadow (by fixed magnifier amount)
                using (Matrix scaleMatrix = new Matrix())
                {
                    scaleMatrix.Scale(
                        (ShadowMagnifier / shapeRectangle.Width) + 1,
                        (ShadowMagnifier / shapeRectangle.Height) + 1);
                    shadowPath.Transform(scaleMatrix);

                    // Center shadow back on the shape
                    RectangleF shadowRectangle = shadowPath.GetBounds();
                    scaleMatrix.Reset();
                    scaleMatrix.Translate(
                        -((shadowRectangle.X + (shadowRectangle.Width / 2)) - (shapeRectangle.X + (shapeRectangle.Width / 2))),
                        -((shadowRectangle.Y + (shadowRectangle.Height / 2)) - (shapeRectangle.Y + (shapeRectangle.Height / 2))));
                    shadowPath.Transform(scaleMatrix);
                }

                // Set the clip region (on the shape)
                using (Region clip = graphics.Clip)
                {
                    graphics.SetClip(shapePath);

                    // Offset the shadow path (move diagonally down-right) from shape
                    using (Matrix translateMatrix = new Matrix())
                    {
                        translateMatrix.Translate((float)shadowOffset.Width, (float)shadowOffset.Height);
                        shadowPath.Transform(translateMatrix);
                    }

                    // Mask-off the shadow from the original shape
                    graphics.SetClip(shadowPath, CombineMode.Complement);
                    graphics.SetClip(clip, CombineMode.Intersect);

                    // Fill the shadow
                    using (PathGradientBrush shadowBrush = new PathGradientBrush(shadowPath))
                    {
                        shadowBrush.CenterColor    = Color.FromArgb(ShadowColorOpacity, ShadowColor);
                        shadowBrush.SurroundColors = new Color[] { Color.Transparent };
                        shadowBrush.FocusScales    = new PointF(ShadowGradientFocalPoint, ShadowGradientFocalPoint);
                        graphics.FillPath(shadowBrush, shadowPath);
                        graphics.ResetClip();
                    }
                }
            }
            finally
            {
                graphics.Restore(state);
            }
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Don't let the lines interfere with clicking on other items
 /// </summary>
 public override bool DoHitTest(IGeometryHost geometryHost, PointD hitPoint, DiagramHitTestInfo hitTestInfo, bool includeTolerance)
 {
     return(false);
 }
Ejemplo n.º 28
0
		/// <summary>
		/// Provide custom shape folding for rectangular fact types
		/// </summary>
		/// <param name="geometryHost">The host view</param>
		/// <param name="potentialPoint">A point on the rectangular boundary of the shape</param>
		/// <param name="vectorEndPoint">A point on the opposite end of the connecting line</param>
		/// <returns>A point on the rectangle edge border</returns>
		public override PointD DoFoldToShape(IGeometryHost geometryHost, PointD potentialPoint, PointD vectorEndPoint)
		{
			NodeShape oppositeShape;
			vectorEndPoint = GeometryUtility.AdjustVectorEndPoint(geometryHost, vectorEndPoint, out oppositeShape);
			PointD? customPoint = GeometryUtility.DoCustomFoldShape(geometryHost, vectorEndPoint, oppositeShape);
			if (customPoint.HasValue)
			{
				return customPoint.Value;
			}
			vectorEndPoint = GeometryUtility.ResolveProxyConnectorVectorEndPoint(vectorEndPoint, oppositeShape);

			// Fold to the shape
			// This is used for center to center routing, so the potential point is the
			// center of the shape. We need to see where a line through the center intersects
			// the rectangle border and return relative coordinates.
			RectangleD bounds = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
			PointD center = bounds.Center;
			vectorEndPoint.Offset(-center.X, -center.Y);
			bool negativeX = vectorEndPoint.X < 0;
			bool negativeY = vectorEndPoint.Y < 0;
			if (VGConstants.FuzzZero(vectorEndPoint.X, VGConstants.FuzzDistance))
			{
				// Vertical line, skip slope calculations
				return new PointD(bounds.Width / 2, negativeY ? 0 : bounds.Height);
			}
			else if (VGConstants.FuzzZero(vectorEndPoint.Y, VGConstants.FuzzDistance))
			{
				// Horizontal line, skip slope calculations
				return new PointD(negativeX ? 0 : bounds.Width, bounds.Height / 2);
			}
			else
			{
				double slope = vectorEndPoint.Y / vectorEndPoint.X;
				// The intersecting line equation is y = mx. We can tell
				// whether to use the vertical or horizontal lines by
				// comparing the relative sizes of the rectangle sides
				// with the slope
				double x;
				double y;
				if (Math.Abs(slope) < (bounds.Height / bounds.Width))
				{
					// Attach to left/right edges
					// Intersect with line x = +/- bounds.Width / 2
					x = bounds.Width / 2;
					if (negativeX)
					{
						x = -x;
					}
					y = x * slope;
				}
				else
				{
					// Attach to top/bottom edges
					// Intersect with line y = +/- bounds.Height / 2
					y = bounds.Height / 2;
					if (negativeY)
					{
						y = -y;
					}
					x = y / slope;
				}
				return new PointD(x + bounds.Width / 2, y + bounds.Height / 2);
			}
		}
Ejemplo n.º 29
0
			public GeometryHostWrapper(IGeometryHost inner)
			{
				myInner = inner;
			}
Ejemplo n.º 30
0
            private static void DrawAssociationEnd(
                DiagramPaintEventArgs e, IGeometryHost geometryHost,
                NodeShape node, PointD pointOnBorder, PointD endPoint,
                bool many, bool optional, bool id, string predicateText, ref PointF?lineEnd, bool bothOptional)
            {
                Pen                pen;
                ShapeElement       shapeHost;
                IOffsetBorderPoint offsetPointProvider;
                Font               font;
                Brush              brush;
                Graphics           g = e.Graphics;

                if (null != (shapeHost = node) &&
                    null != (offsetPointProvider = shapeHost.ShapeGeometry as IOffsetBorderPoint) &&
                    null != (pen = geometryHost.GeometryStyleSet.GetPen(DiagramPens.ConnectionLine)) &&
                    null != (font = geometryHost.GeometryStyleSet.GetFont(DiagramFonts.ConnectionLine)) &&
                    null != (brush = geometryHost.GeometryStyleSet.GetBrush(DiagramBrushes.ConnectionLineText)))
                {
                    Color restoreColor = pen.Color;
                    pen.Color = geometryHost.UpdateGeometryLuminosity(e.View, pen);
                    double angle       = GeometryUtility.CalculateRadiansRotationAngle(endPoint, pointOnBorder);
                    PointD vertexPoint = pointOnBorder;
                    vertexPoint.Offset(CrowsFootHeight * Math.Cos(angle), CrowsFootHeight * Math.Sin(angle));

                    #region draw the main line

                    Pen mainLinePen = (Pen)pen.Clone();
                    if (optional)
                    {
                        mainLinePen.DashPattern = DashPattern;
                        mainLinePen.DashOffset  = DashPattern[0];
                    }
                    if (many & optional)
                    {
                        if (!bothOptional)
                        {
                            g.DrawLine(mainLinePen, PointD.ToPointF(endPoint), PointD.ToPointF(vertexPoint));
                        }
                        else
                        {
                            lineEnd = PointD.ToPointF(vertexPoint);
                        }
                        g.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(pointOnBorder));
                    }
                    else
                    {
                        if (!bothOptional)
                        {
                            g.DrawLine(mainLinePen, PointD.ToPointF(endPoint), PointD.ToPointF(pointOnBorder));
                        }
                        else
                        {
                            lineEnd = PointD.ToPointF(pointOnBorder);
                        }
                    }
                    #endregion
                    #region draw crow's foot if necessary
                    if (many)
                    {
                        PointD?offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, pointOnBorder, vertexPoint, CrowsFootHalfWidth, CrowsFootParallelMode);
                        if (offsetBorderPoint.HasValue)
                        {
                            g.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
                        }
                        offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, pointOnBorder, vertexPoint, -CrowsFootHalfWidth, CrowsFootParallelMode);
                        if (offsetBorderPoint.HasValue)
                        {
                            g.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
                        }
                    }
                    #endregion
                    #region draw tick mark if necessary
                    if (id)
                    {
                        PointD oneMarkLeft = vertexPoint;
                        double cosAngle    = Math.Cos(angle);
                        double sinAngle    = Math.Sin(angle);

                        oneMarkLeft.Offset(InfEngInnerOneMarkOffset * cosAngle, InfEngInnerOneMarkOffset * sinAngle);
                        PointD oneMarkRight = oneMarkLeft;
                        oneMarkLeft.Offset(-InfEngMarkerHalfWidth * sinAngle, InfEngMarkerHalfWidth * cosAngle);
                        oneMarkRight.Offset(InfEngMarkerHalfWidth * sinAngle, -InfEngMarkerHalfWidth * cosAngle);

                        g.DrawLine(pen, PointD.ToPointF(oneMarkLeft), PointD.ToPointF(oneMarkRight));
                    }
                    #endregion
                    #region draw text

                    //determine the line's properties
                    double         edgeX = pointOnBorder.X;
                    double         edgeY = pointOnBorder.Y;
                    EntitySideType whichSideShapeIsOn = EntitySide.FindWhichSide(pointOnBorder, shapeHost.GeometryBoundingBox);
                    double         w = 0;            //, y = 0;
                    angle = Math.Atan2(Math.Abs(endPoint.Y - edgeY), Math.Abs(endPoint.X - edgeX));
                    double inDegrees = angle * 180 / Math.PI;
                    if (inDegrees < 0)
                    {
                        inDegrees += 360;
                    }

                    SizeF textSize = g.MeasureString(predicateText, font);
                    w = textSize.Width;
                    //y = Math.Abs(w * Math.Tan(angle));

                    //determine what to offset
                    double textX      = edgeX;
                    double textY      = edgeY;
                    double h          = textSize.Height;
                    bool   lessThan45 = inDegrees < 45;

                    switch (whichSideShapeIsOn)
                    {
                    case EntitySideType.OnBottom:
                        textY -= TextPaddingY + h;
                        if (lessThan45)
                        {
                            textX += TextPaddingX;
                        }
                        else
                        {
                            textX -= TextPaddingX + w;
                        }
                        break;

                    case EntitySideType.OnTop:
                        textY += TextPaddingY;
                        if (lessThan45)
                        {
                            textX -= TextPaddingX + w;
                        }
                        else
                        {
                            textX += TextPaddingX;
                        }
                        break;

                    case EntitySideType.OnLeft:
                        textX += TextPaddingX;
                        if (lessThan45)
                        {
                            textY -= TextPaddingY + h;
                        }
                        else
                        {
                            textY += TextPaddingY;
                        }
                        break;

                    case EntitySideType.OnRight:
                        textX -= TextPaddingX + w;
                        if (lessThan45)
                        {
                            textY += TextPaddingY;
                        }
                        else
                        {
                            textY -= TextPaddingY + h;
                        }
                        break;
                    }

                    //perform the drawing
                    g.DrawString(predicateText, font, brush, new PointF((float)textX, (float)textY));

                    #endregion

                    pen.Color = restoreColor;
                }
            }
Ejemplo n.º 31
0
 /// <summary>
 /// Gets the suggested connection points of this geometry.
 /// </summary>
 public abstract PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost);
Ejemplo n.º 32
0
			/// <summary>
			/// Paint the solid crowsfoot on the end of an optional line
			/// </summary>
			protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
			{
				EntityRelationshipBinaryMultiplicityDisplay displaySetting = OptionsPage.CurrentEntityRelationshipBinaryMultiplicityDisplay;
				RolePlayerLink connector;
				EdgePointCollection edgePoints;
				int edgePointCount;
				Pen pen;
				ShapeElement shapeHost;
				IOffsetBorderPoint offsetPointProvider;
				if (displaySetting == EntityRelationshipBinaryMultiplicityDisplay.Barker &&
					RoleMultiplicity.ZeroToMany == (connector = (RolePlayerLink)geometryHost).GetDisplayRoleMultiplicity(displaySetting) &&
					null != (edgePoints = connector.EdgePoints) &&
					1 < (edgePointCount = edgePoints.Count) &&
					null != (shapeHost = connector.ToShape) &&
					null != (offsetPointProvider = shapeHost.ShapeGeometry as IOffsetBorderPoint) &&
					null != (pen = geometryHost.GeometryStyleSet.GetPen(DiagramPens.ConnectionLine)))
				{
					Color restoreColor = pen.Color;
					pen.Color = geometryHost.UpdateGeometryLuminosity(e.View, pen);
					PointD pointOnBorder = edgePoints[edgePointCount - 1].Point;
					double angle = GeometryUtility.CalculateRadiansRotationAngle(edgePoints[0].Point, pointOnBorder);
					PointD vertexPoint = pointOnBorder;
					vertexPoint.Offset(CrowsFootHeight * Math.Cos(angle), CrowsFootHeight * Math.Sin(angle));
					e.Graphics.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(pointOnBorder));
					PointD? offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, pointOnBorder, vertexPoint, CrowsFootHalfWidth, CrowsFootParallelMode);
					if (offsetBorderPoint.HasValue)
					{
						e.Graphics.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
					}
					offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, pointOnBorder, vertexPoint, -CrowsFootHalfWidth, CrowsFootParallelMode);
					if (offsetBorderPoint.HasValue)
					{
						e.Graphics.DrawLine(pen, PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
					}
					pen.Color = restoreColor;
				}
				base.DoPaintGeometry(e, geometryHost);
			}
Ejemplo n.º 33
0
			/// <summary>
			/// Return a path modified to include any ER multiplicity decorators
			/// </summary>
			public override GraphicsPath GetPath(IGeometryHost geometryHost)
			{
				EntityRelationshipBinaryMultiplicityDisplay displaySetting = OptionsPage.CurrentEntityRelationshipBinaryMultiplicityDisplay;
				if (displaySetting == EntityRelationshipBinaryMultiplicityDisplay.Off)
				{
					return base.GetPath(geometryHost);
				}
				RolePlayerLink connector = (RolePlayerLink)geometryHost;
				EdgePointCollection edgePoints;
				int edgePointCount;
				RoleMultiplicity multiplicity;
				if (RoleMultiplicity.Unspecified != (multiplicity = connector.GetDisplayRoleMultiplicity(displaySetting)) &&
					1 < (edgePointCount = (edgePoints = connector.EdgePoints).Count))
				{
					switch (displaySetting)
					{
						case EntityRelationshipBinaryMultiplicityDisplay.CrowsFootOnly:
						CrowsFootOnly:
							switch (multiplicity)
							{
								case RoleMultiplicity.OneToMany:
								case RoleMultiplicity.ZeroToMany:
									{
										PointD objectTypeEndPoint = edgePoints[edgePointCount - 1].Point;
										PointD roleBoxEndPoint = edgePoints[0].Point;
										double angle = GeometryUtility.CalculateRadiansRotationAngle(roleBoxEndPoint, objectTypeEndPoint);
										GraphicsPath path = base.UninitializedPath;
										path.Reset();
										path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(objectTypeEndPoint));
										PointD vertexPoint = objectTypeEndPoint;
										vertexPoint.Offset(CrowsFootHeight * Math.Cos(angle), CrowsFootHeight * Math.Sin(angle));
										ShapeElement shapeHost;
										IOffsetBorderPoint offsetPointProvider;
										if (null != (shapeHost = connector.ToShape) &&
											null != (offsetPointProvider = shapeHost.ShapeGeometry as IOffsetBorderPoint))
										{
											PointD? offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, vertexPoint, CrowsFootHalfWidth, CrowsFootParallelMode);
											if (offsetBorderPoint.HasValue)
											{
												path.StartFigure();
												path.AddLine(PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
											}
											offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, vertexPoint, -CrowsFootHalfWidth, CrowsFootParallelMode);
											if (offsetBorderPoint.HasValue)
											{
												path.StartFigure();
												path.AddLine(PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
											}
										}
										return path;
									}
							}
							break;
						case EntityRelationshipBinaryMultiplicityDisplay.Barker:
							// Stop short of the crows foot if optional, draw the broken line under the solid crows foot
							switch (multiplicity)
							{
								case RoleMultiplicity.OneToMany:
									// Single pen only, include the crowsfoot as part of the path
									goto CrowsFootOnly;
								case RoleMultiplicity.ZeroToMany:
									// Stop the path at the vertex point, use a different pen for the crowsfoot in DoPaintGeometry
									{
										PointD objectTypeEndPoint = edgePoints[edgePointCount - 1].Point;
										PointD roleBoxEndPoint = edgePoints[0].Point;
										double angle = GeometryUtility.CalculateRadiansRotationAngle(roleBoxEndPoint, objectTypeEndPoint);
										GraphicsPath path = base.UninitializedPath;
										path.Reset();
										objectTypeEndPoint.Offset(CrowsFootHeight * Math.Cos(angle), CrowsFootHeight * Math.Sin(angle));
										path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(objectTypeEndPoint));
										return path;
									}
							}
							break;
						case EntityRelationshipBinaryMultiplicityDisplay.InformationEngineering:
							{
								PointD objectTypeEndPoint = edgePoints[edgePointCount - 1].Point;
								PointD roleBoxEndPoint = edgePoints[0].Point;
								double angle = GeometryUtility.CalculateRadiansRotationAngle(roleBoxEndPoint, objectTypeEndPoint);
								double cosAngle = Math.Cos(angle);
								double sinAngle = Math.Sin(angle);
								GraphicsPath path = base.UninitializedPath;
								path.Reset();
								switch (multiplicity)
								{
									case RoleMultiplicity.ExactlyOne:
										{
											path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(objectTypeEndPoint));
											path.StartFigure();
											PointD oneMarkLeft = objectTypeEndPoint;
											oneMarkLeft.Offset(InfEngInnerOneMarkOffset * cosAngle, InfEngInnerOneMarkOffset * sinAngle);
											PointD oneMarkRight = oneMarkLeft;
											oneMarkLeft.Offset(-InfEngMarkerHalfWidth * sinAngle, InfEngMarkerHalfWidth * cosAngle);
											oneMarkRight.Offset(InfEngMarkerHalfWidth * sinAngle, -InfEngMarkerHalfWidth * cosAngle);
											path.AddLine(PointD.ToPointF(oneMarkLeft), PointD.ToPointF(oneMarkRight));
											oneMarkLeft.Offset(InfEngOuterOneMarkOffset * cosAngle, InfEngOuterOneMarkOffset * sinAngle);
											oneMarkRight.Offset(InfEngOuterOneMarkOffset * cosAngle, InfEngOuterOneMarkOffset * sinAngle);
											path.StartFigure();
											path.AddLine(PointD.ToPointF(oneMarkLeft), PointD.ToPointF(oneMarkRight));
											break;
										}
									case RoleMultiplicity.ZeroToOne:
										{
											PointD circleStart = objectTypeEndPoint;
											circleStart.Offset((InfEngInnerOneMarkOffset + InfEngOuterOneMarkOffset + InfEngMarkerHalfWidth + InfEngMarkerHalfWidth) * cosAngle, (InfEngInnerOneMarkOffset + InfEngOuterOneMarkOffset + InfEngMarkerHalfWidth + InfEngMarkerHalfWidth) * sinAngle);
											path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(circleStart));
											circleStart.Offset(-InfEngMarkerHalfWidth * cosAngle, -InfEngMarkerHalfWidth * sinAngle);
											path.StartFigure();
											path.AddArc(
												(float)(circleStart.X - InfEngMarkerHalfWidth),
												(float)(circleStart.Y - InfEngMarkerHalfWidth),
												(float)(InfEngMarkerHalfWidth + InfEngMarkerHalfWidth),
												(float)(InfEngMarkerHalfWidth + InfEngMarkerHalfWidth),
												0,
												360);
											circleStart.Offset(-InfEngMarkerHalfWidth * cosAngle, -InfEngMarkerHalfWidth * sinAngle);
											path.StartFigure();
											path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(objectTypeEndPoint));
											circleStart.Offset(-InfEngOuterOneMarkOffset * cosAngle, -InfEngOuterOneMarkOffset * sinAngle);
											PointD oneMarkRight = circleStart;
											circleStart.Offset(-InfEngMarkerHalfWidth * sinAngle, InfEngMarkerHalfWidth * cosAngle);
											oneMarkRight.Offset(InfEngMarkerHalfWidth * sinAngle, -InfEngMarkerHalfWidth * cosAngle);
											path.StartFigure();
											path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(oneMarkRight));
											break;
										}
									case RoleMultiplicity.ZeroToMany:
										{
											PointD circleStart = objectTypeEndPoint;
											circleStart.Offset((CrowsFootHeight + InfEngMarkerHalfWidth + InfEngMarkerHalfWidth) * cosAngle, (CrowsFootHeight + InfEngMarkerHalfWidth + InfEngMarkerHalfWidth) * sinAngle);
											path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(circleStart));
											circleStart.Offset(-InfEngMarkerHalfWidth * cosAngle, -InfEngMarkerHalfWidth * sinAngle);
											path.StartFigure();
											path.AddArc(
												(float)(circleStart.X - InfEngMarkerHalfWidth),
												(float)(circleStart.Y - InfEngMarkerHalfWidth),
												(float)(InfEngMarkerHalfWidth + InfEngMarkerHalfWidth),
												(float)(InfEngMarkerHalfWidth + InfEngMarkerHalfWidth),
												0,
												360);
											circleStart.Offset(-InfEngMarkerHalfWidth * cosAngle, -InfEngMarkerHalfWidth * sinAngle);
											path.StartFigure();
											path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(objectTypeEndPoint));

											ShapeElement shapeHost;
											IOffsetBorderPoint offsetPointProvider;
											if (null != (shapeHost = connector.ToShape) &&
												null != (offsetPointProvider = shapeHost.ShapeGeometry as IOffsetBorderPoint))
											{
												path.StartFigure();
												path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(objectTypeEndPoint));
												PointD? offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, circleStart, CrowsFootHalfWidth, CrowsFootParallelMode);
												if (offsetBorderPoint.HasValue)
												{
													path.StartFigure();
													path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(offsetBorderPoint.Value));
												}
												offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, circleStart, -CrowsFootHalfWidth, CrowsFootParallelMode);
												if (offsetBorderPoint.HasValue)
												{
													path.StartFigure();
													path.AddLine(PointD.ToPointF(circleStart), PointD.ToPointF(offsetBorderPoint.Value));
												}
											}
											break;
										}
									case RoleMultiplicity.OneToMany:
										{
											path.AddLine(PointD.ToPointF(roleBoxEndPoint), PointD.ToPointF(objectTypeEndPoint));
											PointD vertexPoint = objectTypeEndPoint;
											vertexPoint.Offset(CrowsFootHeight * cosAngle, CrowsFootHeight * sinAngle);

											// Add the one mark
											PointD oneMarkLeft = vertexPoint;
											oneMarkLeft.Offset(InfEngOuterOneMarkOffset * cosAngle, InfEngOuterOneMarkOffset * sinAngle);
											PointD oneMarkRight = oneMarkLeft;
											oneMarkLeft.Offset(-InfEngMarkerHalfWidth * sinAngle, InfEngMarkerHalfWidth * cosAngle);
											oneMarkRight.Offset(InfEngMarkerHalfWidth * sinAngle, -InfEngMarkerHalfWidth * cosAngle);
											path.StartFigure();
											path.AddLine(PointD.ToPointF(oneMarkLeft), PointD.ToPointF(oneMarkRight));

											ShapeElement shapeHost;
											IOffsetBorderPoint offsetPointProvider;
											if (null != (shapeHost = connector.ToShape) &&
												null != (offsetPointProvider = shapeHost.ShapeGeometry as IOffsetBorderPoint))
											{
												PointD? offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, vertexPoint, CrowsFootHalfWidth, CrowsFootParallelMode);
												if (offsetBorderPoint.HasValue)
												{
													path.StartFigure();
													path.AddLine(PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
												}
												offsetBorderPoint = offsetPointProvider.OffsetBorderPoint(shapeHost, objectTypeEndPoint, vertexPoint, -CrowsFootHalfWidth, CrowsFootParallelMode);
												if (offsetBorderPoint.HasValue)
												{
													path.StartFigure();
													path.AddLine(PointD.ToPointF(vertexPoint), PointD.ToPointF(offsetBorderPoint.Value));
												}
											}
											break;
										}
								}
								return path;
							}
					}
				}
				return base.GetPath(geometryHost);
			}
Ejemplo n.º 34
0
 /// <summary>
 /// Gets the suggested connection points of this geometry.
 /// </summary>
 /// <value></value>
 public override PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost)
 {
     return(null);
 }
Ejemplo n.º 35
0
        /// <summary>
        /// Override of DoHitTest so it works with non-rectilinear line segments
        /// </summary>
        public override bool DoHitTest(IGeometryHost geometryHost, PointD hitPoint, DiagramHitTestInfo hitTestInfo, bool includeTolerance)
        {
            bool        retVal      = false;
            LineSegment hitSegment  = null;
            AnchorPoint anchorPoint = null;
            // In DSL Tools v8.2, GetHitTestTolerance is an instance method, but in DSL Tools v9.0, it is a static method.
            // We call it without a qualifier here so that it will compile against both versions.
            SizeD      tolerance = GetHitTestTolerance(hitTestInfo);
            RectangleD perimeter = this.GetPerimeterBoundingBox(geometryHost);

            perimeter.Inflate(tolerance);
            if (perimeter.Contains(hitPoint))
            {
                LineSegment[] segments     = this.CalculateSegments(geometryHost, hitTestInfo);
                int           segmentCount = segments.Length;
                for (int i = 0; i < segmentCount; ++i)
                {
                    LineSegment testSegment = segments[i];
                    RectangleD  testBounds  = GeometryHelpers.RectangleDFrom2Pts(testSegment.StartPoint, testSegment.EndPoint);
                    testBounds.Inflate(tolerance);
                    if (testBounds.Contains(hitPoint))
                    {
                        anchorPoint = TestHitAnchor(geometryHost as BinaryLinkShape, testSegment, tolerance, hitPoint);
                        if (anchorPoint != null)
                        {
                            retVal     = true;
                            hitSegment = testSegment;
                            break;
                        }
                        double distance = DistanceFromPointToLine(hitPoint, testSegment.StartPoint, testSegment.EndPoint, true);
                        if (!double.IsNaN(distance) && distance < (tolerance.Width + geometryHost.GeometryStyleSet.GetPen(geometryHost.GeometryOutlinePenId).Width / 2f))
                        {
                            retVal     = true;
                            hitSegment = testSegment;
                            break;
                        }
                    }
                }
            }
            if (hitTestInfo != null)
            {
                DiagramItem diagramItem;
                if (retVal)
                {
                    if (anchorPoint == null)
                    {
                        // In DSL Tools v8.2, CreateDiagramItem is an instance method, but in DSL Tools v9.0, it is a static method.
                        // We call it without a qualifier here so that it will compile against both versions.
                        diagramItem = CreateDiagramItem(geometryHost, hitSegment);
                    }
                    else
                    {
                        diagramItem = new DiagramItem(geometryHost as LinkShape, hitSegment, anchorPoint);
                    }
                }
                else
                {
                    diagramItem = null;
                }
                hitTestInfo.HitDiagramItem = diagramItem;
                hitTestInfo.HitGrabHandle  = null;
            }
            return(retVal);
        }
Ejemplo n.º 36
0
        /// <summary>
        /// Replacement for BinaryLinkShapeGeometry.DoPaintGeometry
        /// </summary>
        protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
        {
            LinkShape            linkShape;
            IJumpFreeLinkShape   jumpFreeShape;
            VGObjectLineJumpCode expectedJumpCode;

            if (null != (jumpFreeShape = geometryHost as IJumpFreeLinkShape) &&
                null != (linkShape = geometryHost as LinkShape) &&
                linkShape.RouteJumpType != (expectedJumpCode = (jumpFreeShape.IsJumpFree ? VGObjectLineJumpCode.VGObjectJumpCodeNever : VGObjectLineJumpCode.VGObjectJumpCodePage)))
            {
                // Backup plan, sometimes we can't set this during configuration, and
                // it tends to revert in undo/redo scenarios when the backing graph
                // wrapper is not preserved.
                linkShape.RouteJumpType = expectedJumpCode;
            }
            Graphics           g     = e.Graphics;
            GraphicsPath       path  = this.GetPath(geometryHost);
            StyleSetResourceId penId = GetOutlinePenId(geometryHost);
            Pen pen = geometryHost.GeometryStyleSet.GetPen(penId);

            if ((path != null) && (pen != null))
            {
                IDynamicColorGeometryHost dynamicColors = geometryHost as IDynamicColorGeometryHost;
                if (this.HasOutline(geometryHost))
                {
                    Color restoreColor;
                    if (null == (dynamicColors = geometryHost as IDynamicColorGeometryHost) ||
                        (restoreColor = dynamicColors.UpdateDynamicColor(penId, pen)).IsEmpty)
                    {
                        restoreColor = geometryHost.UpdateGeometryLuminosity(e.View, pen);
                    }
                    else
                    {
                        geometryHost.UpdateGeometryLuminosity(e.View, pen);
                    }
                    GeometryUtility.SafeDrawPath(g, pen, path);
                    pen.Color = restoreColor;
                }
                IBinaryLinkGeometryData hostData;
                EdgePointCollection     edgePoints;
                int edgePointCount;
                if (null != (hostData = geometryHost as IBinaryLinkGeometryData) &&
                    null != (edgePoints = hostData.GeometryEdgePoints) &&
                    1 < (edgePointCount = edgePoints.Count))
                {
                    float         rotationAngle = 0f;
                    LinkDecorator decorator;
                    if (null != (decorator = hostData.GeometryDecoratorFrom))
                    {
                        rotationAngle = CalculateRotationAngle(edgePoints[0].Point, edgePoints[1].Point);
                        DrawDecorator(e, geometryHost, rotationAngle, edgePoints[0].Point, decorator
#if VISUALSTUDIO_10_0
                                      , hostData.GeometryDecoratorFromSize
#endif
                                      );
                    }
                    if (null != (decorator = hostData.GeometryDecoratorTo))
                    {
                        rotationAngle = CalculateRotationAngle(edgePoints[edgePointCount - 1].Point, edgePoints[edgePointCount - 2].Point);
                        DrawDecorator(e, geometryHost, rotationAngle, edgePoints[edgePointCount - 1].Point, decorator
#if VISUALSTUDIO_10_0
                                      , hostData.GeometryDecoratorToSize
#endif
                                      );
                    }
                }
            }
        }
 /// <summary>
 /// Gets the suggested connection points of this geometry.
 /// </summary>
 public abstract PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost);
		/// <summary>
		/// Don't let the lines interfere with clicking on other items
		/// </summary>
		public override bool DoHitTest(IGeometryHost geometryHost, PointD hitPoint, DiagramHitTestInfo hitTestInfo, bool includeTolerance)
		{
			return false;
		}
Ejemplo n.º 39
0
		/// <summary>
		/// Provide custom shape folding for rectangular fact types
		/// </summary>
		/// <param name="geometryHost">The host view</param>
		/// <param name="potentialPoint">A point on the rectangular boundary of the shape</param>
		/// <param name="vectorEndPoint">A point on the opposite end of the connecting line</param>
		/// <returns>A point on the rounded rectangle border</returns>
		public override PointD DoFoldToShape(IGeometryHost geometryHost, PointD potentialPoint, PointD vectorEndPoint)
		{
			// Get an endpoint we can work with
			NodeShape oppositeShape;
			vectorEndPoint = GeometryUtility.AdjustVectorEndPoint(geometryHost, vectorEndPoint, out oppositeShape);
			PointD? customPoint = GeometryUtility.DoCustomFoldShape(geometryHost, vectorEndPoint, oppositeShape);
			if (customPoint.HasValue)
			{
				return customPoint.Value;
			}
			vectorEndPoint = GeometryUtility.ResolveProxyConnectorVectorEndPoint(vectorEndPoint, oppositeShape);

			// This is used for center to center routing, so the potential point is the
			// center of the shape. We need to see where a line through the center intersects
			// the rectangle border and return relative coordinates.
			RectangleD bounds = geometryHost.TranslateGeometryToAbsoluteBounds(geometryHost.GeometryBoundingBox);
			PointD center = bounds.Center;
			vectorEndPoint.Offset(-center.X, -center.Y);
			bool negativeX = vectorEndPoint.X < 0;
			bool negativeY = vectorEndPoint.Y < 0;
			if (VGConstants.FuzzZero(vectorEndPoint.X, VGConstants.FuzzDistance))
			{
				// Vertical line, skip slope calculations
				return new PointD(bounds.Width / 2, negativeY ? 0 : bounds.Height);
			}
			else if (VGConstants.FuzzZero(vectorEndPoint.Y, VGConstants.FuzzDistance))
			{
				// Horizontal line, skip slope calculations
				return new PointD(negativeX ? 0 : bounds.Width, bounds.Height / 2);
			}
			else
			{
				double slope = vectorEndPoint.Y / vectorEndPoint.X;
				// The intersecting line equation is y = mx. We can tell
				// whether to use the vertical or horizontal lines by
				// comparing the relative sizes of the rectangle sides
				// with the slope
				double x;
				double y;
				double r = Radius;
				double halfHeight = bounds.Height / 2;
				double halfWidth = bounds.Width / 2;
				bool cornerHit;
				if (Math.Abs(slope) < (bounds.Height / bounds.Width))
				{
					// Attach to left/right edges
					// Intersect with line x = +/- bounds.Width / 2
					x = halfWidth;
					if (negativeX)
					{
						x = -x;
					}
					y = x * slope;
					cornerHit = Math.Abs(y) > (halfHeight - r);
				}
				else
				{
					// Attach to top/bottom edges
					// Intersect with line y = +/- bounds.Height / 2
					y = halfHeight;
					if (negativeY)
					{
						y = -y;
					}
					x = y / slope;
					cornerHit = Math.Abs(x) > (halfWidth - r);
				}
				if (cornerHit)
				{
					// The equation here is significantly more complicated than
					// other shapes because of the off center circle, which is
					// centered at (ccx, ccy) in these equations. The raw equations are:
					// (x - ccx)^2 + (y - ccy)^2 = r^2
					// y = m*x where m is the slope
					// Solving for x gives (algebra is non-trivial and ommitted):
					// v1 = 1 + m*m
					// v2 = m*ccx + ccy
					// v3 = sqrt(r^2*v1 - v2^2)
					// x = (+/-v3 + ccx-m*ccy)/v1
					// Note that picking the correct center is absolutely necessary.
					// Unlike the other shapes, where all lines will pass the ellipse/circle
					// at some point, the off-center circle means that choosing the wrong
					// center will result in an unsolvable equation (taking the square
					// root will throw).
					double ccx = halfWidth - r; // Corner center x value
					double ccy = halfHeight - r; // Corner center y value
					bool useNegativeSquareRoot = false;
					if (negativeX) // Left quadrants
					{
						ccx = -ccx;
						useNegativeSquareRoot = true;
						if (!negativeY)
						{
							// Lower left quadrant
							ccy = -ccy;
						}
					}
					else if (!negativeY) // Right quadrants
					{
						// Lower right quadrant
						ccy = -ccy;
					}
					double v1 = 1 + slope * slope;
					double v2 = slope * ccx + ccy;
					double v3 = Math.Sqrt(r * r * v1 - v2 * v2);
					if (useNegativeSquareRoot)
					{
						v3 = -v3;
					}
					x = (v3 + ccx - slope * ccy) / v1;
					y = slope * x;
				}
				return new PointD(x + halfWidth, y + halfHeight);
			}
		}
		/// <summary>
		/// Replacement for BinaryLinkShapeGeometry.DoPaintGeometry
		/// </summary>
		protected override void DoPaintGeometry(DiagramPaintEventArgs e, IGeometryHost geometryHost)
		{
			LinkShape linkShape = geometryHost as LinkShape;
			if (linkShape != null &&
				linkShape.RouteJumpType != VGObjectLineJumpCode.VGObjectJumpCodeNever)
			{
				// Backup plan, sometimes we can't set this during configuration, and
				// it tends to revert in undo/redo scenarios when the backing graph
				// wrapper is not preserved.
				linkShape.RouteJumpType = VGObjectLineJumpCode.VGObjectJumpCodeNever;
			}
			Graphics g = e.Graphics;
			GraphicsPath path = this.GetPath(geometryHost);
			StyleSetResourceId penId = GetOutlinePenId(geometryHost);
			Pen pen = geometryHost.GeometryStyleSet.GetPen(penId);
			if ((path != null) && (pen != null))
			{
				IDynamicColorGeometryHost dynamicColors = geometryHost as IDynamicColorGeometryHost;
				if (this.HasOutline(geometryHost))
				{
					Color restoreColor;
					if (null == (dynamicColors = geometryHost as IDynamicColorGeometryHost) ||
						(restoreColor = dynamicColors.UpdateDynamicColor(penId, pen)).IsEmpty)
					{
						restoreColor = geometryHost.UpdateGeometryLuminosity(e.View, pen);
					}
					else
					{
						geometryHost.UpdateGeometryLuminosity(e.View, pen);
					}
					GeometryUtility.SafeDrawPath(g, pen, path);
					pen.Color = restoreColor;
				}
				IBinaryLinkGeometryData hostData;
				EdgePointCollection edgePoints;
				int edgePointCount;
				if (null != (hostData = geometryHost as IBinaryLinkGeometryData) &&
					null != (edgePoints = hostData.GeometryEdgePoints) &&
					1 < (edgePointCount = edgePoints.Count))
				{
					float rotationAngle = 0f;
					LinkDecorator decorator;
					if (null != (decorator = hostData.GeometryDecoratorFrom))
					{
						rotationAngle = CalculateRotationAngle(edgePoints[0].Point, edgePoints[1].Point);
						DrawDecorator(e, geometryHost, rotationAngle, edgePoints[0].Point, decorator
#if VISUALSTUDIO_10_0
							, hostData.GeometryDecoratorFromSize
#endif
						);
					}
					if (null != (decorator = hostData.GeometryDecoratorTo))
					{
						rotationAngle = CalculateRotationAngle(edgePoints[edgePointCount - 1].Point, edgePoints[edgePointCount - 2].Point);
						DrawDecorator(e, geometryHost, rotationAngle, edgePoints[edgePointCount - 1].Point, decorator
#if VISUALSTUDIO_10_0
							, hostData.GeometryDecoratorToSize
#endif
							);
					}
				}
			}
		}
		/// <summary>
		/// Replacement for LinkShapeGeometry.DrawDecorator
		/// </summary>
#if VISUALSTUDIO_10_0
		protected static new void DrawDecorator(DiagramPaintEventArgs e, IGeometryHost geometryHost, float rotation, PointD centerRight, LinkDecorator decorator, SizeD size)
		{
        /// <summary>
        /// Draws the shape's shadow.
        /// </summary>
        /// <remarks>
        /// The shadow is replaced with a glow.
        /// </remarks>
        protected override void DoPaintShadow(DiagramPaintEventArgs e, IGeometryHost geometryHost)
        {
            Guard.NotNull(() => geometryHost, geometryHost);
            Guard.NotNull(() => e, e);

            Graphics graphics = e.Graphics;
            GraphicsState state = graphics.Save();
            SizeD shadowOffset = this.ShadowOffset;
            try
            {
                GraphicsPath shapePath = this.GetPath(geometryHost);
                RectangleF shapeRectangle = shapePath.GetBounds();

                // Create shadow path
                GraphicsPath shadowPath = shapePath.Clone() as GraphicsPath;

                // Enlarge the shadow (by fixed magnifier amount)
                using (Matrix scaleMatrix = new Matrix())
                {
                    scaleMatrix.Scale(
                        (ShadowMagnifier / shapeRectangle.Width) + 1,
                        (ShadowMagnifier / shapeRectangle.Height) + 1);
                    shadowPath.Transform(scaleMatrix);

                    // Center shadow back on the shape
                    RectangleF shadowRectangle = shadowPath.GetBounds();
                    scaleMatrix.Reset();
                    scaleMatrix.Translate(
                        -((shadowRectangle.X + (shadowRectangle.Width / 2)) - (shapeRectangle.X + (shapeRectangle.Width / 2))),
                        -((shadowRectangle.Y + (shadowRectangle.Height / 2)) - (shapeRectangle.Y + (shapeRectangle.Height / 2))));
                    shadowPath.Transform(scaleMatrix);
                }

                // Set the clip region (on the shape)
                using (Region clip = graphics.Clip)
                {
                    graphics.SetClip(shapePath);

                    // Offset the shadow path (move diagonally down-right) from shape
                    using (Matrix translateMatrix = new Matrix())
                    {
                        translateMatrix.Translate((float)shadowOffset.Width, (float)shadowOffset.Height);
                        shadowPath.Transform(translateMatrix);
                    }

                    // Mask-off the shadow from the original shape
                    graphics.SetClip(shadowPath, CombineMode.Complement);
                    graphics.SetClip(clip, CombineMode.Intersect);

                    // Fill the shadow
                    using (PathGradientBrush shadowBrush = new PathGradientBrush(shadowPath))
                    {
                        shadowBrush.CenterColor = Color.FromArgb(ShadowColorOpacity, ShadowColor);
                        shadowBrush.SurroundColors = new Color[] { Color.Transparent };
                        shadowBrush.FocusScales = new PointF(ShadowGradientFocalPoint, ShadowGradientFocalPoint);
                        graphics.FillPath(shadowBrush, shadowPath);
                        graphics.ResetClip();
                    }
                }
            }
            finally
            {
                graphics.Restore(state);
            }
        }
		protected static new void DrawDecorator(DiagramPaintEventArgs e, IGeometryHost geometryHost, float rotation, PointD centerRight, LinkDecorator decorator)
		{
			SizeD size = LinkShapeGeometry.SizeDecorator;
#endif
			double offsetBy = 0d;
			bool doOffset = false;
			ILinkDecoratorSettings settings = decorator as ILinkDecoratorSettings;
			if (settings != null)
			{
				size = settings.DecoratorSize;
				offsetBy = settings.OffsetBy;
				doOffset = !VGConstants.FuzzZero(offsetBy, VGConstants.FuzzDistance);
			}
			Graphics g = e.Graphics;
			RectangleD boundingRect = new RectangleD(centerRight.X - size.Width, centerRight.Y - (size.Height / 2), size.Width, size.Height);
			Matrix rotationMatrix = g.Transform;
			float offsetX = 0f;
			float offsetY = 0f;
			if (doOffset)
			{
				double rotationRadians = rotation * Math.PI / 180;
				offsetX = (float)(offsetBy * Math.Cos(rotationRadians));
				offsetY = (float)(offsetBy * Math.Sin(rotationRadians));
				rotationMatrix.Translate(offsetX, offsetY);
			}
			rotationMatrix.RotateAt(rotation, PointD.ToPointF(centerRight));
			g.Transform = rotationMatrix;
			decorator.DoPaintShape(boundingRect, geometryHost, e);
			rotationMatrix.RotateAt(-rotation, PointD.ToPointF(centerRight));
			if (doOffset)
			{
				rotationMatrix.Translate(-offsetX, -offsetY);
			}
			g.Transform = rotationMatrix;
		}
 /// <summary>
 /// Gets the suggested connection points of this geometry.
 /// </summary>
 /// <value></value>
 public override PointD[] GetGeometryConnectionPoints(IGeometryHost geometryHost)
 {
     return null;
 }
Ejemplo n.º 45
0
		/// <summary>
		/// Implements <see cref="IOffsetBorderPoint.OffsetBorderPoint"/>
		/// </summary>
		protected PointD? OffsetBorderPoint(IGeometryHost geometryHost, PointD borderPoint, PointD outsidePoint, double offset, bool parallelVector)
		{
			double angle = GeometryUtility.CalculateRadiansRotationAngle(outsidePoint, borderPoint);

			// Get the sample point
			PointD samplePoint = borderPoint;
			samplePoint.Offset(-offset * Math.Sin(angle), offset * Math.Cos(angle));

			// Figure out the slope, either parallel to the incoming line, or pointed at the outside point
			PointD slopeThrough = parallelVector ? borderPoint : samplePoint;

			// Translate the rectangle to the origin
			RectangleD bounds = geometryHost.GeometryBoundingBox;
			PointD hostCenter = bounds.Center;
			samplePoint.Offset(-hostCenter.X, -hostCenter.Y);

			double px = samplePoint.X;
			double py = samplePoint.Y;
			double solvedX;
			double solvedY;

			if (VGConstants.FuzzEqual(slopeThrough.X, outsidePoint.X, VGConstants.FuzzDistance))
			{
				// Vertical line, hit the same edge as the border point
				if (Math.Abs(px) > (bounds.Width / 2 + VGConstants.FuzzDistance))
				{
					// Line hits outside rectangle
					return null;
				}
				solvedX = px;
				solvedY = borderPoint.Y - hostCenter.Y;
			}
			else if (VGConstants.FuzzEqual(slopeThrough.Y, outsidePoint.Y, VGConstants.FuzzDistance))
			{
				// Horizontal line, hit the same edge as the border point
				if (Math.Abs(py) > (bounds.Height / 2 + VGConstants.FuzzDistance))
				{
					// Line hits outside rectangle
					return null;
				}
				solvedY = py;
				solvedX = borderPoint.X - hostCenter.X;
			}
			else
			{
				int hitCount = 0;
				solvedX = 0;
				solvedY = 0;
				double solvedXAlternate = 0;
				double solvedYAlternate = 0;

				// We've already checked vertical and horizontal lines, so we know the lines will intersect either
				// zero or two sides of the rectangle. Find the two sides.
				// The intersecting line equation is y = m(x - px) + py (solved for y) or x = 1/m(y-py) + px (solved for x)
				// The rectangle borders are y = halfHeight, y = -halfHeight, x = halfWidth, x = -halfWidth
				double halfWidth = bounds.Width / 2;
				double halfHeight = bounds.Height / 2;

				double slope = (outsidePoint.Y - slopeThrough.Y) / (outsidePoint.X - slopeThrough.X);
				double inverseSlope = 1 / slope;

				double testIntersect;
				
				// Top edge
				testIntersect = inverseSlope * (halfHeight - py) + px;
				if (Math.Abs(testIntersect) < (halfWidth + VGConstants.FuzzDistance))
				{
					solvedX = testIntersect;
					solvedY = halfHeight;
					hitCount = 1;
				}

				// Bottom edge
				testIntersect = inverseSlope * (-halfHeight - py) + px;
				if (Math.Abs(testIntersect) < (halfWidth + VGConstants.FuzzDistance))
				{
					if (hitCount == 1)
					{
						solvedXAlternate = testIntersect;
						solvedYAlternate = -halfHeight;
					}
					else
					{
						solvedX = testIntersect;
						solvedY = -halfHeight;
					}
					++hitCount;
				}

				// Right edge
				if (hitCount != 2)
				{
					testIntersect = slope * (halfWidth - px) + py;
					if (Math.Abs(testIntersect) < (halfHeight + VGConstants.FuzzDistance))
					{
						if (hitCount == 1)
						{
							solvedYAlternate = testIntersect;
							solvedXAlternate = halfWidth;
						}
						else
						{
							solvedY = testIntersect;
							solvedX = halfWidth;
						}
						++hitCount;
					}
				}

				// Left edge
				if (hitCount != 2)
				{
					testIntersect = slope * (-halfWidth - px) + py;
					if (Math.Abs(testIntersect) < (halfHeight + VGConstants.FuzzDistance))
					{
						if (hitCount == 1)
						{
							solvedYAlternate = testIntersect;
							solvedXAlternate = -halfWidth;
						}
						else
						{
							solvedY = testIntersect;
							solvedX = -halfWidth;
						}
						++hitCount;
					}
				}

				// Choose the best match and translate the point back out
				if (hitCount == 2)
				{
					// Find the point closest to the sample point
					double xDif = px - solvedX;
					double yDif = py - solvedY;
					double xDifAlternate = px - solvedXAlternate;
					double yDifAlternate = py - solvedYAlternate;
					if ((xDif * xDif + yDif * yDif) > (xDifAlternate * xDifAlternate + yDifAlternate * yDifAlternate))
					{
						solvedX = solvedXAlternate;
						solvedY = solvedYAlternate;
					}
				}
				else
				{
					// Unsolvable
					return null;
				}
			}
			return new PointD(solvedX + hostCenter.X, solvedY + hostCenter.Y);
		}