I have the scenario as follows, I am drawing an arc between two points in WPF, I need to fill the arc, but I want to fill the arc sector touching the center, but WPF fills up differently. How do I get the arc filled up the way I want?
PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = start;
ArcSegment arc = new ArcSegment(end, new Size(radiusX, radiusY), 0.0, large, d, true); //large & d corresponds to size & direction
pathFigure.Segments.Add(arc);
pathGeometry.Figures.Add(pathFigure);
SolidColorBrush fill = new SolidColorBrush(color);
drawingContext.DrawGeometry(fill, pen, pathGeometry);
My code produces the output as this :
whereas my requirement is this one:
Is there a way of getting this done? TIA.
Sure, you just need at add a line segment to go along with your arc segment.
PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = start;
ArcSegment arc = new ArcSegment(end, new Size(radiusX, radiusY), 0.0, large, d, true); //large & d corresponds to size & direction
pathFigure.Segments.Add(arc);
//line segment takes the path to the origin
LineSegment line = new LineSegment(new Point(originX, originY), true);
pathFigure.Segments.Add(line );
pathGeometry.Figures.Add(pathFigure);
SolidColorBrush fill = new SolidColorBrush(color);
drawingContext.DrawGeometry(fill, pen, pathGeometry);
Related
I would like to know how can I draw an arc in C# , I'm trying using DrawEllipse but it doesn't work and it give wrong drawing.
However, I have searched for a method to draw an arc in the Class DrawingContext but I didn't find it.
DrawingVisual d = new DrawingVisual();
System.Windows.Media.Pen pen = new System.Windows.Media.Pen();
DrawingContext drawingContext = d.RenderOpen();
pen.Brush = System.Windows.Media.Brushes.Black;
System.Windows.Point center = new System.Windows.Point();
center.X = 0.4;
center.Y = 0.5;
drawingContext.DrawEllipse(System.Windows.Media.Brushes.White, pen, center, 4,4);
drawingContext.Close();
canvas.Children.Add(new VisualHost { Visual = d });
You would have to draw a PathGeometry or a StreamGeometry that contains an arc segment, like the following circular arc of radius 100 from (100,100) to (200,200):
var visual = new DrawingVisual();
var pen = new Pen(Brushes.Black, 1);
using (var dc = visual.RenderOpen())
{
var figure = new PathFigure
{
StartPoint = new Point(100, 100) // start point
};
figure.Segments.Add(new ArcSegment
{
Point = new Point(200, 200), // end point
Size = new Size(100, 100), // radii
SweepDirection = SweepDirection.Clockwise
});
var geometry = new PathGeometry();
geometry.Figures.Add(figure);
dc.DrawGeometry(null, pen, geometry);
}
I am trying to write my own pie chart control using WPF. I have created a function that returns a Path object representing a segment of the pie chart. When I use this to generate a graph where the largest slice is less then or equal to 50% of the graph it renders fine and looks like so:
But when one of the arcsegments has an angle of more then PI radians the radius is not equal all the way round and it looks like this:
Here is the code that I have written to draw each segment of the chart:
public Path CreateSlice(Point centerPoint, double radius, ref Point initialPoint, ref double totalAngle, double sliceAngle, Color sliceColor)
{
//A set of connected simple graphics objects that makes up the Slice graphic
Path slicePath = new Path();
slicePath.Fill = new SolidColorBrush(sliceColor);
slicePath.Stroke = new SolidColorBrush(Colors.White);
slicePath.StrokeThickness = 2;
PathGeometry pathGeometry = new PathGeometry();
PathFigureCollection pathFigureCollection = new PathFigureCollection();
PathSegmentCollection sliceSegmentCollection = new PathSegmentCollection();
//The path figure describes the shape in the slicePath object using geometry
PathFigure pathFigure = new PathFigure();
pathFigure.StartPoint = centerPoint;//Set the start point to the center of the pie chart
//Representing the first line of the slice from the centerpoint to the initial point
//I.E one length of the slice
LineSegment firstLineSegment = new LineSegment();
firstLineSegment.Point = initialPoint;
sliceSegmentCollection.Add(firstLineSegment);
//Calculate the next point along the circle that the slice should arc too.
//This point is calculated using the total angle used of the pie chart including this slice
totalAngle += sliceAngle;
//Calculate the X and Y coordinates of the next point
double x = centerPoint.X + radius * Math.Cos(totalAngle);
double y = centerPoint.Y + radius * Math.Sin(totalAngle);
initialPoint = new Point(x, y);
//Represents the arc segment of the slice
ArcSegment sliceArcSegment = new ArcSegment();
sliceArcSegment.Point = initialPoint;
sliceArcSegment.SweepDirection = SweepDirection.Clockwise;
sliceArcSegment.Size = new Size(radius, radius);
sliceSegmentCollection.Add(sliceArcSegment);
//Representing the second line of the slice from the second point back to the center
LineSegment secondLineSegment = new LineSegment();
secondLineSegment.Point = centerPoint;
sliceSegmentCollection.Add(secondLineSegment);
pathFigure.Segments = sliceSegmentCollection;
pathFigureCollection.Add(pathFigure);
pathGeometry.Figures = pathFigureCollection;
slicePath.Data = pathGeometry;
return slicePath;
}
Could anyone help me figure out how to draw a arcsegment with a uniform radius all the way round please.
The IsLargeArc property should be set in these cases to tell the arc to be greater than 180 degrees. Looking at your figure it is capping the degrees at 180 and shifting the expected center point of the Arc.
I've stumbled upon converting Ellipse to PathGeometry.
I've tried to use ArcSegment to present Ellipse, but still don't know how to convert Ellipse size to ArcSegment size. I'm trying to segment Ellipse into two part, but there are other approaches, i.e. Bezier curves.
Need clues how to convert Ellipse to ArcSegment collection.
The whole process could be looking like that:
public static PathFigure ToFigures(this Ellipse ellipse)
{
var pathFigure = new PathFigure {IsClosed = true};
var arcSegment1 = new ArcSegment();
var arcSegment2 = new ArcSegment();
pathFigure.Segments.Add(arcSegment1);
pathFigure.Segments.Add(arcSegment2);
return pathFigure;
}
You could directly use an EllipseGeometry for the Path Data:
path = new Path
{
Data = new EllipseGeometry { RadiusX = 100, RadiusY = 50 }
};
Using the size of the Ellipse it would look like this:
path = new Path
{
Data = new EllipseGeometry
{
RadiusX = ellipse.ActualWidth / 2,
RadiusY = ellipse.ActualHeight / 2
}
};
I want to draw the Shape as in the image. I have drawn half circle using Arc Segment, Now I want to draw Quarter circle, or A Sector, But I am unable to draw it.
I used this code to draw Arc, I tried to change the size, and the angle is also not working.
What should I do to draw Quarter circle / Sector ?? Code I used to draw Arc is :
PathFigure pthFigure1 = new PathFigure();
pthFigure1.StartPoint = new Point(50, 60);// starting cordinates of arcs
ArcSegment arcSeg1 = new ArcSegment();
arcSeg1.Point = new Point(100, 82); // ending cordinates of arcs
arcSeg1.Size = new Size(10, 10);
arcSeg1.IsLargeArc = false;
arcSeg1.SweepDirection = SweepDirection.Clockwise;
arcSeg1.RotationAngle = 90;
PathSegmentCollection myPathSegmentCollection1 = new PathSegmentCollection();
myPathSegmentCollection1.Add(arcSeg1);
pthFigure1.Segments = myPathSegmentCollection1;
PathFigureCollection pthFigureCollection1 = new PathFigureCollection();
pthFigureCollection1.Add(pthFigure1);
PathGeometry pthGeometry1 = new PathGeometry();
pthGeometry1.Figures = pthFigureCollection1;
System.Windows.Shapes.Path arcPath1 = new System.Windows.Shapes.Path();
arcPath1.Data = pthGeometry1;
arcPath1.Fill = new SolidColorBrush(Color.FromArgb(255, 255, 23, 0));
this.LayoutRoot.Children.Add(arcPath1);
With minimum changes to your code (/**/ signifies changed or added lines).
PathFigure pthFigure1 = new PathFigure();
/**/ pthFigure1.StartPoint = new Point(0, 100);// starting cordinates of arcs
ArcSegment arcSeg1 = new ArcSegment();
/**/ arcSeg1.Point = new Point(100, 0); // ending cordinates of arcs
/**/ arcSeg1.Size = new Size(100, 100);
arcSeg1.IsLargeArc = false;
arcSeg1.SweepDirection = SweepDirection.Clockwise;
/**/ LineSegment lineSeg = new LineSegment();
/**/ lineSeg.Point = new Point(100,100);
PathSegmentCollection myPathSegmentCollection1 = new PathSegmentCollection();
myPathSegmentCollection1.Add(arcSeg1);
/**/ myPathSegmentCollection1.Add(lineSeg);
pthFigure1.Segments = myPathSegmentCollection1;
PathFigureCollection pthFigureCollection1 = new PathFigureCollection();
pthFigureCollection1.Add(pthFigure1);
...
It seems that you missinterpret the meaning of ArcSegment.RotationAngle.
The math of it:
What is the best solution for getting the middle point of an ArcSegment in a path and label it in WPF?
This should work:
//the given arc (or any other segments)
var arc = new ArcSegment(
point: new Point(200, 100),
size: new Size(100, 50),
rotationAngle: 90,
isLargeArc: true,
sweepDirection: SweepDirection.Counterclockwise,
isStroked: true);
//compose one or more segments into a collection
var pathcoll = new PathSegmentCollection();
pathcoll.Add(arc);
//create a figure based on the set of segments
var figure = new PathFigure();
figure.Segments = pathcoll;
//compose a collection of figures
var figcoll = new PathFigureCollection();
figcoll.Add(figure);
//create a path-geometry using the figures collection
var geom = new PathGeometry(figcoll);
double fraction = 0.5; //the relative point of the curve
Point pt; //the absolute point of the curve
Point tg; //the tangent point of the curve
geom.GetPointAtFractionLength(
fraction,
out pt,
out tg);
Hope it helps.
Cheers