## #1,147 – Converting from Polar Coordinates to Cartesian Coordinates

You can represent a two dimensional point as either a cartesian coordinate (X,Y) or a polar coordinate (r,theta).  Conversions between these two coordinate systems are shown below.

From polar coordinates to cartesian: To convert from cartesian coordinates to polar, the following formula works, as long as the X value is positive. If X is 0 or negative, then the calculation for theta becomes: Advertisements

## #1,146 – Polar Coordinate System

In most cases when you’re working with graphical objects, you use a cartesian coordinate system, where each point is represented as an X and a Y value, indicating the point’s distance from an origin in two different dimensions.

You can also express points in a two-dimensional system using a polar coordinate system.  Each point in a polar coordinate system is represented with two values:

• A radius value, describing how far the point is from an origin  (range is any non-negative number)
• An angular coordinate, describing how many degrees around the circle the point is located, typically from a horizontal ray extending to the right of the origin  (range typically [0, 360) degrees or [0, 2*pi) radians)

Below is a picture showing two sample points expressed in polar coordinates.

• (2.0, 60) – Radius = 2, Angle = 60 degrees (counterclockwise) from horizontal
• (1.0, 180) – Radius = 1, Angle = 180 degrees (counterclockwise) from horizontal ## #1,145 – Using RenderSize in Custom Shape

When drawing a geometry in a custom Shape element, you could draw using hard-coded coordinates.  It’s more common, however, to use the RenderSize property of the UIElement to render the object so that the geometry scales based on the size of the control.

Below, we create a custom shape that draws a diagonal line from the upper left corner of the control to the lower right.

```    public class MyShape : Shape
{
protected override Geometry DefiningGeometry
{
get
{
double maxWidth = RenderSize.Width;
double maxHeight = RenderSize.Height;

StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext ctx = geom.Open())
{
ctx.BeginFigure(
new Point(0.0, 0.0),
false,
false);
ctx.LineTo(
new Point(maxWidth, maxHeight),
true,
false);
}

return geom;
}
}
}
```

We can use the shape in XAML as follows:

```    <StackPanel>
<loc:MyShape Stroke="Black" StrokeThickness="1"
Height="50" Width="50"
HorizontalAlignment="Center"/>
</StackPanel>
```

Now when we change the size of the underlying control, the geometry adjusts as well.   ## #1,144 – Geometry in Custom Shape Doesn’t Automatically Scale

If you define a custom Shape by creating some Geometry, the resulting geometry will not automatically scale when shape’s size is changed.

Suppose that we have the following custom shape.

```    public class MyShape : Shape
{
protected override Geometry DefiningGeometry
{
get
{
StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext ctx = geom.Open())
{
ctx.BeginFigure(
new Point(0.0, 0.0),
false,
false);
ctx.LineTo(
new Point(50.0, 50.0),
true,
false);
}

return geom;
}
}
}
```

Placing this control in a StackPanel, it’s size is just large enough to accommodate the geometry. If we explicitly make the shape larger, the underlying geometry stays the same size. ## #1,143 – Coordinate System for StreamGeometry

You can use a StreamGeometry object, along with the StreamGeometryContext returned by its Open method, to draw simple geometric shapes.

When using the various methods of a StreamGeometryContext instance, you work with X and Y values.  The coordinate system used has the upper left corner of the drawing region at (0,0), with X values increasing from left to right and Y values increasing from top to bottom. Below, we have a custom shape that draws a line segment from (0,0) to (50,50) and then another line segment to (75,25).

```    public class MyShape : Shape
{
protected override Geometry DefiningGeometry
{
get
{
return GetMyShapeGeometry();
}
}

private Geometry GetMyShapeGeometry()
{
StreamGeometry geom = new StreamGeometry();
using (StreamGeometryContext ctx = geom.Open())
{
ctx.BeginFigure(
new Point(0.0, 0.0),
false,    // is NOT filled
false);   // is NOT closed
ctx.LineTo(
new Point(50.0, 50.0),
true,     // is stroked (line visible)
false);   // is not smoothly joined w/other segments
ctx.LineTo(
new Point(75.0, 25.0),
true,     // is stroked (line visible)
false);   // is not smoothly joined w/other segments
}

return geom;
}
}
```

We can then use this shape from XAML.

```    <Canvas>
<loc:MyShape Canvas.Top="0" Canvas.Left="0"
Stroke="Black" />
</Canvas>
``` ## #1,142 – Setting Attached Property Value from Code

You can change the value of an attached property for a given control from code by using the SetValue or SetCurrentValue methods.  You call these methods on the control that the property is attached to, passing in a reference to the property and the new value.  (SetCurrentValue is preferred, to avoid overwriting a local value).

Below, we set a value for MyAttProps.Important in XAML, but also wire up a Click event to allow changing the value from code.

```        <Label x:Name="lblHi" Content="Hi there"
loc:MyAttProps.Important="True"
Background="AliceBlue"/>
<Button Content="Change Content"
Click="Button_Click"/>
```

In the code-behind, we use SetCurrentValue to change the value.

```        private void Button_Click(object sender, RoutedEventArgs e)
{
bool impValue = (bool)lblHi.GetValue(MyAttProps.ImportantProperty);

lblHi.SetCurrentValue(MyAttProps.ImportantProperty, !impValue);
}
```

## #1,141 – Attached Properties Allow Customization of Existing Controls

An attached property is a dependency property defined in one class and then attached (used) on an instance of some other class.

You can define your own attached properties as a mechanism for extending the appearance or behavior of a control.

Below, we register a dependency property of type bool, named Important.  When Important is set to true, we set the foreground brush of the control to red.

```    public class MyAttProps
{
// Surround property definition
static PropertyMetadata ImportantMetadata =
new PropertyMetadata(
false,                // Default value
OnImportantChanged,   // Changed callback
null);                // Coerce value callback

public static readonly DependencyProperty ImportantProperty =
DependencyProperty.RegisterAttached(
"Important",          // Property name
typeof(bool),         // Property type
typeof(MyAttProps),   // Defining class type
ImportantMetadata);   // Metadata described above

// Allow setting value from XAML
public static void SetImportant(DependencyObject depObj, bool value)
{
depObj.SetValue(ImportantProperty, value);
}

public static bool GetImportant(DependencyObject depObj)
{
return (bool)depObj.GetValue(ImportantProperty);
}

// Important property has changed
public static void OnImportantChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
Control ctrl = d as Control;
bool important = (bool)e.NewValue;
if ((ctrl != null) && important)
ctrl.SetValue(Control.ForegroundProperty, Brushes.Red);
else
ctrl.ClearValue(Control.ForegroundProperty);
}
}
```

We can now use this new property from XAML:

```        <Label x:Name="lblHi" Content="Hi there"
loc:MyAttProps.Important="True"
Background="AliceBlue"/>
``` 