captncraig
captncraig

Reputation: 23118

Filled Arcs in WPF

I am trying to draw a figure something like this:Concentric arcs

I need to have a unique element for each arc segment that I can handle events on and recolor as I need. I am a bit unsure on how to create the proper geometries in WPF. I can easily calculate the four points for each arc segment from the radius of the circles and the angle from center. Using a radius of 100 for the outer circle and 50 for the inner, the four points in red are (clockwise from top left with origin at top of circle):

0,0
70,30
35,65
0,50

Using these points I create a simple path to draw the segment:

<Path Stroke="Black" Fill="Black" StrokeThickness="1" >
  <Path.Data>
    <PathGeometry>
      <PathGeometry.Figures>
        <PathFigure StartPoint="0,0">
          <PathFigure.Segments>
            <ArcSegment Point="70,30" />
            <LineSegment Point="35,65" />
            <ArcSegment Point="0,50" />
          </PathFigure.Segments>
        </PathFigure>
      </PathGeometry.Figures>
    </PathGeometry>
  </Path.Data>
</Path>

But that just draws a trapezoid with straight lines. I know I can alter the Size on the ArcSegments, but I can't seem to figure out how that affects the curvature. I want the arcs to follow the main circle, but I am not sure how to express that. How can I make the arcs have the right curvature?

Also, how do I express and add paths in the c# code behind,rather than in the xaml?

Upvotes: 5

Views: 13699

Answers (3)

Sandeep Jadhav
Sandeep Jadhav

Reputation: 928

XAML Code

<Window x:Class="PopupTargetElement.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"         
        mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">        
    <Grid>
        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="360" Fill="#FFF4F4F5" HorizontalAlignment="Center" Height="300"
                Stretch="None" Stroke="Black" StartAngle="0" VerticalAlignment="Center" Width="300"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="360" Fill="#FFF4F4F5" HorizontalAlignment="Center" Height="220"
            Stretch="None" Stroke="Black" StartAngle="0" VerticalAlignment="Center" Width="220"/>
        
        <Ellipse   Width="140"  Height="140" Fill="Black" Stroke="Black" StrokeThickness="1" />

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="45" Fill="Black" HorizontalAlignment="Center" Height="300" 
            Stretch="None" Stroke="Black" StartAngle="0" VerticalAlignment="Center" Width="300"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="135" Fill="Black" HorizontalAlignment="Center" Height="300"
            Stretch="None" Stroke="Black" StartAngle="90" VerticalAlignment="Center" Width="300"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel"  EndAngle="225" Fill="Black" HorizontalAlignment="Center" Height="300" 
            Stretch="None" Stroke="Black" StartAngle="180" VerticalAlignment="Center" Width="300"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel"  EndAngle="315" Fill="Black" HorizontalAlignment="Center" Height="300"
            Stretch="None" Stroke="Black" StartAngle="270" VerticalAlignment="Center" Width="300"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="90" Fill="Black" HorizontalAlignment="Center" Height="220" 
            Stretch="None" Stroke="Black" StartAngle="45" VerticalAlignment="Center" Width="220"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="180" Fill="Black" HorizontalAlignment="Center" Height="220" 
                Stretch="None" Stroke="Black" StartAngle="135" VerticalAlignment="Center" Width="220"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="270" Fill="Black" HorizontalAlignment="Center" Height="220"
            Stretch="None" Stroke="Black" StartAngle="225" VerticalAlignment="Center" Width="220"/>

        <ed:Arc ArcThickness="40" ArcThicknessUnit="Pixel" EndAngle="360" Fill="Black" HorizontalAlignment="Center" Height="220"
            Stretch="None" Stroke="Black" StartAngle="315" VerticalAlignment="Center" Width="220"/>
    </Grid>
</Window>

Add the assembly reference in your project. Microsoft.Expression.Drawing

for xmlns:ed=http://schemas.microsoft.com/expression/2010/drawing

Output

enter image description here

Upvotes: 2

NotAgain
NotAgain

Reputation: 1977

One more option can be to pull in expression 2010 drawing namespace into the XAML. It makes it easy then.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" x:Class="Arcs.MainWindow"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <ed:Arc ArcThickness="30"
            ArcThicknessUnit="Pixel"
            StartAngle="30"
            EndAngle="130"
            HorizontalAlignment="Left"
            Height="179" Margin="195,62,0,0"
            Stretch="None"
            Stroke="CornflowerBlue"
            Fill ="CornflowerBlue"
            VerticalAlignment="Top"
            Width="179" />
</Grid>

EDIT: This will pull in "Microsoft.Expression.Drawing" which gets installed when you install Blend. If the client machine does not have this then this will fail. On the other hand you can package and redistribute the dll with your software. Microsoft allows that.

Upvotes: 0

Will Dean
Will Dean

Reputation: 39520

I've drawn exactly that sort of shape (two coaxial arcs and two radials joining them) like this:

new LineSegment(new Point(x2, y2), true),
new ArcSegment(new Point(x3,y3),new Size(100*outerRadius,100*outerRadius), 0,largeAngle, SweepDirection.Clockwise, true),
new LineSegment(new Point(x4, y4), true),
new ArcSegment(new Point(x1, y1),new Size(100*innerRadius,100*innerRadius), 0,largeAngle, SweepDirection.Counterclockwise, true),

Obviously that's code rather than XAML, but it might give you a kick-start.

Upvotes: 5

Related Questions