/// <summary> /// Performs a hit test on the <see cref="InvariantEllipsePrimitive"/> at a given point. /// </summary> /// <param name="point">The mouse position in destination coordinates.</param> /// <returns> /// <b>True</b> if <paramref name="point"/> "hits" the <see cref="InvariantEllipsePrimitive"/>, /// <b>false</b> otherwise. /// </returns> /// <remarks> /// A "hit" is defined as when the mouse position is <see cref="VectorGraphic.HitTestDistance"/> /// screen pixels away from any point on the arc. /// </remarks> public override bool HitTest(Point point) { this.CoordinateSystem = CoordinateSystem.Source; bool result = EllipsePrimitive.HitTest( this.SpatialTransform.ConvertToSource(point), this.Rectangle, this.SpatialTransform); this.ResetCoordinateSystem(); return(result); }
/// <summary> /// Gets the point where the ellipse intersects the line whose end points /// are the center of the ellipse and the specified point. /// </summary> /// <param name="point">A point in either source or destination coordinates.</param> /// <returns>The point on the graphic closest to the given <paramref name="point"/>.</returns> /// <remarks> /// <para> /// Depending on the value of <see cref="Graphic.CoordinateSystem"/>, /// the computation will be carried out in either source /// or destination coordinates.</para> /// </remarks> public override PointF GetClosestPoint(PointF point) { // Semi major/minor axes float a = this.Width / 2; float b = this.Height / 2; // Center of ellipse RectangleF rect = this.Rectangle; float x1 = rect.Left + a; float y1 = rect.Top + b; PointF center = new PointF(x1, y1); return(EllipsePrimitive.IntersectEllipseAndLine(a, b, center, point)); }
internal static PointF GetClosestPoint( PointF point, RectangleF boundingBox, float startAngle, float sweepAngle) { // Semi major/minor axes float a = boundingBox.Width / 2; float b = boundingBox.Height / 2; // Center of ellipse float x1 = boundingBox.Left + a; float y1 = boundingBox.Top + b; // normalize the angles float normalizedSweepAngle = Math.Sign(sweepAngle) * Math.Min(360, Math.Abs(sweepAngle)); float normalizedStartAngle = startAngle % 360; if (normalizedStartAngle < 0) { normalizedStartAngle += 360; } float normalizedEndAngle = (normalizedStartAngle + normalizedSweepAngle); if (normalizedSweepAngle < 0) { //swap start and end angles float t = normalizedStartAngle; normalizedStartAngle = normalizedEndAngle; normalizedEndAngle = t; //the sweep angle is now positive normalizedSweepAngle *= -1; } // find the closest endpoint const double degreesToRadians = Math.PI / 180; PointF center = new PointF(x1, y1); double normalizedStartAngleRadians = normalizedStartAngle * degreesToRadians; double normalizedEndAngleRadians = normalizedEndAngle * degreesToRadians; PointF start = new PointF(center.X + a * (float)Math.Cos(normalizedStartAngleRadians), center.Y + b * (float)Math.Sin(normalizedStartAngleRadians)); PointF end = new PointF(center.X + a * (float)Math.Cos(normalizedEndAngleRadians), center.Y + b * (float)Math.Sin(normalizedEndAngleRadians)); float distanceToStartX = start.X - point.X; float distanceToStartY = start.Y - point.Y; float distanceToEndX = end.X - point.X; float distanceToEndY = end.Y - point.Y; float squareDistanceToStart = distanceToStartX * distanceToStartX + distanceToStartY * distanceToStartY; float squareDistanceToEnd = distanceToEndX * distanceToEndX + distanceToEndY * distanceToEndY; PointF closestPoint = (squareDistanceToStart < squareDistanceToEnd) ? start : end; float minSquareDistance = Math.Min(squareDistanceToStart, squareDistanceToEnd); // find the intersection along the ray eminating from center towards point, and calculate its angle from the x-axis PointF result = EllipsePrimitive.IntersectEllipseAndLine(a, b, center, point); //Check if the angle between 'start' and 'result' is positive and less than 'sweep'. double angleStartToPoint = Vector.SubtendedAngle(result, center, start); if (angleStartToPoint < normalizedSweepAngle && angleStartToPoint > 0) { float distanceToResultX = result.X - point.X; float distanceToResultY = result.Y - point.Y; float squareDistanceToResult = distanceToResultX * distanceToResultX + distanceToResultY * distanceToResultY; if (squareDistanceToResult < minSquareDistance) { closestPoint = result; } } return(closestPoint); }