Plot Geometry
This section defines a Plot
utility to give a graphical visualization of GDAL geometries
in a Xaml Window Page using a Canvas as a Cartesian Plan where to put the coordinates of
the geometries.
Drawing coordinates with svg patterns
Geometries in the Canvas are rendered as Paths
whose Data
property follows
the Standard Vector Graphics pattern. A path consists of a sequence of path
segments and each path segment consists of a sequence of commands where the first defines a new
current position and the remainder define a line or curve from the current position to some new
position which becomes the current position for the next part of the curve and so on. The form of the
path element is as follows:
1:
|
|
The example above defines a path that consists of establishing a
current position at the origin (M
ove to 0,0) and the path goes from there to the point (100,100) as a
straight L
ine.
We define specific functions for each shapes type (points, line, rings) that return their path data as svg strings.
Points will be rendered graphically as little squares whose dimension must be choosen in a way appropriate to give a sense of a puntual shape.
Fo this reason the pointPath
function takes an (x,y)
argument representing the point's coordinates
together with a scale
argument. The function will return the svg reppresentation of a little square
centered at the point's coordinates and sized at the given scale as to give a sense of a
punctual shape. The square will have a side of 6 points in a Canvas of 400 x 400 points.
and so the scale should be calculated dividing the actual bounding box by 400.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
|
The linePath
function takes a list representing a line's coordinatesand returns its svg reppresentation.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
Rings are the base elements of an OGR Polygon. Actually they are just lines but they have to be drawn in a different way for the Xaml Engine to fill the space they enclose with a solid color.
The ringPath
function takes a list representing a ring's coordinates and returns its
svg reppresentation.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
Creating Canvas Paths from OGR.Geometries
OGR includes different geometry types that for our purpose can be rendered as the same shape type.
Below we define 3 classes of shapes (for points, lines and polygons) that actually we will
draw on the canvas, plus a ShapeCollection
type to treat each type of Geometry Collection
or Multi-Geometry. For these two last we won't draw just a single shape but more shapes at
the same time.
Then we define the toShape
function that maps an OGR.Geometry to the appropiate shape.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: |
|
Below we will define a global shapePath
function that actually will return a
path only for geometry types that can be classified as points, lines or
polygons. For every other geometry types the function will fail.
First of all we need to extract the coordinates from the OGR.Geometries.
The coordinates
function extracts a list of tuples made of the x (longitude
if we are in a geographic space) and y (latitude) coordinates that constitute
the geometry:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
While we already have function to calculate the svg pattern for point and line geometries we have not defined a corresponding function for polygons but instead a function for rings.
An OGR Polygon is a complex structure made of one or more rings. In this case we need to traverse the geometry structure to find all its rings and then concatenates their svg reppresentation in a single string.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: |
|
Frequently will be plotting more geometries in the same chart and to distinguish one from the others we will have to choose a different color.
Colors in Xaml are rendered by Brushes
so we define a getRandomBrush
function that
will return each time a Brush
with a new random color:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
|
Since now, the function defined above return paths as strings. The toPath
function below returns
the actual Xaml Path
that we will add to the canvas for each OGR.Geometry
that is simple i.e.
is a point, a line or a polygon. Then we will define a more generic toPaths
function that for
every type of geometry (either simple or compound) will return a list of shapes to be drawn on the
Canvas.
The scale
argument is needed to re-scale the sapes based on the fraction of the current bounding
box respect to the 400 x 400 points Canvas. To re-scale the shapes we use the RenderTransform
property
of the Path
. (More on the RenderTransform
property below.)
The seed
argument is needed to feed the getRandomBrush
function to have a real random color.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: |
|
Setting the Canvas space: OGR.Envelope and RenderTransform
We need to set the space of the cartesian plan represented by the Canvas at a size and at a position that makes the shape visibile.
First with env
we extract the bounding box of the geometry as an
OGR.Envelope
1: 2: 3: 4: 5: |
|
... then we resize
it based on a choosen zoom
as a percentage of the
shape size. If the geometry is made of just a point it has not a real size
so in this case we just calculate a margin based on the coordinate's magnitude.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: |
|
RenderTranform
can be used to scale, skew, rotate and translate a wpf control.
We will use the envelop information to calculate 1) the appropriate renderTransform both to scale the sapes in the canvas to render them bigger or smaller enough to be visibile; and 2) to translate the canvas at the shape positions
The pattern used by the property is:
1:
|
|
Drawing a coordinates grid on X and Y Axis
Now before to define the final Plot
class a little tricky thing.
I want to see on my canvas not only the geometries but also the scale at which they have been drawn. So I need to draw steps on the X and Y Axis with the associated coordinate number at the given scale.
The steps
function writes the coordinate number on the steps:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
The blackPath
function returns the Xaml Path for a black line at the given coordinates
and will be used to draw both the x and y axis and also the single steps lines on them.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: |
|
Finally the axisXY
draws on a give Canvas the X and Y axis, the steps on them
and writes the numbers of their coordinates.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: |
|
Saving a Canvas as an Image
Since I need to write this documentation and I don't want to take a print screen for each plot I made, I will define a save function to convert the canvas in a png immage and save it on my drive.
The saveAsBitmap
function just do this for me:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: |
|
The Plot utility class
Armed with all the function defined above we can finally implement our Plot
utility and
to render it flexible enough to add future functionalities we define it as a plain F# Class:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: |
|
Full name: Plot-geometry.stringPath
Full name: Plot-geometry.pointPath
Takes a `scale` argument and a tuple reppresenting a point' coordinates type and returns the svg
reppresentation of a little square centered at the point's coordinates and sized
at the given scale as to give a sense of a punctual shape. The square will have
a side of 6 points in a Canvas of 400 x 400 points. The appropriate scale should
be calculated dividing the actual bounding box by 400.
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Full name: Plot-geometry.linePath
Takes and a list representing a line's coordinates and returns its svg reppresentation as a string.
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
Full name: Microsoft.FSharp.Collections.List.fold
Full name: Plot-geometry.ringPath
Takes a list representing a ring's coordinates and returns its svg reppresentation as a string.
| Point
| Line
| Polygon
| ShapeCollection
Full name: Plot-geometry.Shape
Classes of shapes reppresenting OGR.Geometries.
union case Shape.Point: Shape
--------------------
type Point =
struct
new : x:float * y:float -> Point
member Equals : o:obj -> bool + 1 overload
member GetHashCode : unit -> int
member Offset : offsetX:float * offsetY:float -> unit
member ToString : unit -> string + 1 overload
member X : float with get, set
member Y : float with get, set
static member Add : point:Point * vector:Vector -> Point
static member Equals : point1:Point * point2:Point -> bool
static member Multiply : point:Point * matrix:Matrix -> Point
...
end
Full name: System.Windows.Point
--------------------
Point()
Point(x: float, y: float) : unit
union case Shape.Line: Shape
--------------------
type Line =
inherit Shape
new : unit -> Line
member X1 : float with get, set
member X2 : float with get, set
member Y1 : float with get, set
member Y2 : float with get, set
static val X1Property : DependencyProperty
static val Y1Property : DependencyProperty
static val X2Property : DependencyProperty
static val Y2Property : DependencyProperty
Full name: System.Windows.Shapes.Line
--------------------
Line() : unit
union case Shape.Polygon: Shape
--------------------
type Polygon =
inherit Shape
new : unit -> Polygon
member FillRule : FillRule with get, set
member Points : PointCollection with get, set
static val PointsProperty : DependencyProperty
static val FillRuleProperty : DependencyProperty
Full name: System.Windows.Shapes.Polygon
--------------------
Polygon() : unit
Full name: Plot-geometry.geomType
Just an utility function to more easily get the OGR.Geometry type.
type Geometry =
new : type:wkbGeometryType -> Geometry + 2 overloads
member AddGeometry : other:Geometry -> int
member AddGeometryDirectly : other_disown:Geometry -> int
member AddPoint : x:float * y:float * z:float -> unit
member AddPoint_2D : x:float * y:float -> unit
member Area : unit -> float
member AssignSpatialReference : reference:SpatialReference -> unit
member Boundary : unit -> Geometry
member Buffer : distance:float * quadsecs:int -> Geometry
member Centroid : unit -> Geometry
...
Full name: OSGeo.OGR.Geometry
--------------------
OGR.Geometry(type: OGR.wkbGeometryType) : unit
OGR.Geometry(cPtr: nativeint, cMemoryOwn: bool, parent: obj) : unit
OGR.Geometry(type: OGR.wkbGeometryType, wkt: string, wkb: int, wkb_buf: nativeint, gml: string) : unit
Full name: Plot-geometry.toShape
Maps an OGR.Geometry to the appropriate shape if the mapping is known and
fails in the other case.
| wkbUnknown = 0
| wkbPoint = 1
| wkbLineString = 2
| wkbPolygon = 3
| wkbMultiPoint = 4
| wkbMultiLineString = 5
| wkbMultiPolygon = 6
| wkbGeometryCollection = 7
| wkbNone = 100
| wkbLinearRing = 101
...
Full name: OSGeo.OGR.wkbGeometryType
Full name: Microsoft.FSharp.Core.Operators.failwith
Full name: Plot-geometry.coordinates
Extracts the geometry's coordinates as a list of tuples made of
longitude and latitude.
Full name: Plot-geometry.shapePath
Returns the appropriate path for geometry types that can be classified as
points, lines or polygons. Fails for every other geometry types.
Full name: Microsoft.FSharp.Collections.List.head
Full name: Plot-geometry.getRandomBrush
Returna a `Brush` with a new random color.
Full name: Microsoft.FSharp.Core.Operators.typeof
static member AliceBlue : SolidColorBrush
static member AntiqueWhite : SolidColorBrush
static member Aqua : SolidColorBrush
static member Aquamarine : SolidColorBrush
static member Azure : SolidColorBrush
static member Beige : SolidColorBrush
static member Bisque : SolidColorBrush
static member Black : SolidColorBrush
static member BlanchedAlmond : SolidColorBrush
static member Blue : SolidColorBrush
...
Full name: System.Windows.Media.Brushes
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
Full name: Microsoft.FSharp.Collections.Array.map
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float
Full name: System.Random
--------------------
Random() : unit
Random(Seed: int) : unit
Random.Next(maxValue: int) : int
Random.Next(minValue: int, maxValue: int) : int
type BrushConverter =
inherit TypeConverter
new : unit -> BrushConverter
member CanConvertFrom : context:ITypeDescriptorContext * sourceType:Type -> bool
member CanConvertTo : context:ITypeDescriptorContext * destinationType:Type -> bool
member ConvertFrom : context:ITypeDescriptorContext * culture:CultureInfo * value:obj -> obj
member ConvertTo : context:ITypeDescriptorContext * culture:CultureInfo * value:obj * destinationType:Type -> obj
Full name: System.Windows.Media.BrushConverter
--------------------
BrushConverter() : unit
type SolidColorBrush =
inherit Brush
new : unit -> SolidColorBrush + 1 overload
member Clone : unit -> SolidColorBrush
member CloneCurrentValue : unit -> SolidColorBrush
member Color : Color with get, set
static val ColorProperty : DependencyProperty
static member DeserializeFrom : reader:BinaryReader -> obj
Full name: System.Windows.Media.SolidColorBrush
--------------------
SolidColorBrush() : unit
SolidColorBrush(color: Color) : unit
Full name: Plot-geometry.toPath
Maps a simple OGR.Geometry to a Xaml Path.
type Path =
inherit Shape
new : unit -> Path
member Data : Geometry with get, set
static val DataProperty : DependencyProperty
Full name: System.Windows.Shapes.Path
--------------------
Path() : unit
namespace System.Windows.Media
--------------------
namespace System.Media
inherit Animatable
member Bounds : Rect
member Clone : unit -> Geometry
member CloneCurrentValue : unit -> Geometry
member FillContains : hitPoint:Point -> bool + 3 overloads
member FillContainsWithDetail : geometry:Geometry -> IntersectionDetail + 1 overload
member GetArea : unit -> float + 1 overload
member GetFlattenedPathGeometry : unit -> PathGeometry + 1 overload
member GetOutlinedPathGeometry : unit -> PathGeometry + 1 overload
member GetRenderBounds : pen:Pen -> Rect + 1 overload
member GetWidenedPathGeometry : pen:Pen -> PathGeometry + 1 overload
...
Full name: System.Windows.Media.Geometry
inherit GeneralTransform
member Clone : unit -> Transform
member CloneCurrentValue : unit -> Transform
member Inverse : GeneralTransform
member TransformBounds : rect:Rect -> Rect
member TryTransform : inPoint:Point * result:Point -> bool
member Value : Matrix
static member Identity : Transform
static member Parse : source:string -> Transform
Full name: System.Windows.Media.Transform
Full name: Plot-geometry.toPaths
Maps any OGR.Geometry (simple or compound) to a a Xaml Paths list.
Full name: Microsoft.FSharp.Collections.List.concat
Full name: Plot-geometry.toEnv
Extracs the bounding box of the geometry.
type Envelope =
new : unit -> Envelope + 1 overload
member Dispose : unit -> unit
member MaxX : float with get, set
member MaxY : float with get, set
member MinX : float with get, set
member MinY : float with get, set
static member getCPtr : obj:Envelope -> HandleRef
static member getCPtrAndDisown : obj:Envelope * parent:obj -> HandleRef
static member getCPtrAndSetReference : obj:Envelope * parent:obj -> HandleRef
Full name: OSGeo.OGR.Envelope
--------------------
OGR.Envelope() : unit
OGR.Envelope(cPtr: nativeint, cMemoryOwn: bool, parent: obj) : unit
Full name: Plot-geometry.resize
Resizes the envelope based on a choosen zoom.
Full name: Plot-geometry.renderTransformString
Full name: Plot-geometry.steps
Writes the coordinate number at the given x y coordinates.
type Canvas =
inherit Panel
new : unit -> Canvas
static val LeftProperty : DependencyProperty
static val TopProperty : DependencyProperty
static val RightProperty : DependencyProperty
static val BottomProperty : DependencyProperty
static member GetBottom : element:UIElement -> float
static member GetLeft : element:UIElement -> float
static member GetRight : element:UIElement -> float
static member GetTop : element:UIElement -> float
static member SetBottom : element:UIElement * length:float -> unit
...
Full name: System.Windows.Controls.Canvas
--------------------
Canvas() : unit
type TextBlock =
inherit FrameworkElement
new : unit -> TextBlock + 1 overload
member Background : Brush with get, set
member BaselineOffset : float with get, set
member BreakAfter : LineBreakCondition
member BreakBefore : LineBreakCondition
member ContentEnd : TextPointer
member ContentStart : TextPointer
member FontFamily : FontFamily with get, set
member FontSize : float with get, set
member FontStretch : FontStretch with get, set
...
Full name: System.Windows.Controls.TextBlock
--------------------
TextBlock() : unit
TextBlock(inline: Documents.Inline) : unit
Full name: Plot-geometry.blackPath
Returns the Xaml Path for a black line at the given coordinates.
Full name: Plot-geometry.axisXY
Full name: Microsoft.FSharp.Core.Operators.ignore
static member AliceBlue : Color
static member AntiqueWhite : Color
static member Aqua : Color
static member Aquamarine : Color
static member Azure : Color
static member Beige : Color
static member Bisque : Color
static member Black : Color
static member BlanchedAlmond : Color
static member Blue : Color
...
Full name: System.Windows.Media.Colors
Full name: Plot-geometry.saveAsBitmap
Saves a canvas as a png image of a given width and height size to a given fileName
type Size =
struct
new : width:float * height:float -> Size
member Equals : o:obj -> bool + 1 overload
member GetHashCode : unit -> int
member Height : float with get, set
member IsEmpty : bool
member ToString : unit -> string + 1 overload
member Width : float with get, set
static member Empty : Size
static member Equals : size1:Size * size2:Size -> bool
static member Parse : source:string -> Size
end
Full name: System.Windows.Size
--------------------
Size()
Size(width: float, height: float) : unit
type RenderTargetBitmap =
inherit BitmapSource
new : pixelWidth:int * pixelHeight:int * dpiX:float * dpiY:float * pixelFormat:PixelFormat -> RenderTargetBitmap
member Clear : unit -> unit
member Render : visual:Visual -> unit
Full name: System.Windows.Media.Imaging.RenderTargetBitmap
--------------------
RenderTargetBitmap(pixelWidth: int, pixelHeight: int, dpiX: float, dpiY: float, pixelFormat: PixelFormat) : unit
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
static member Bgr101010 : PixelFormat
static member Bgr24 : PixelFormat
static member Bgr32 : PixelFormat
static member Bgr555 : PixelFormat
static member Bgr565 : PixelFormat
static member Bgra32 : PixelFormat
static member BlackWhite : PixelFormat
static member Cmyk32 : PixelFormat
static member Default : PixelFormat
static member Gray16 : PixelFormat
...
Full name: System.Windows.Media.PixelFormats
type PngBitmapEncoder =
inherit BitmapEncoder
new : unit -> PngBitmapEncoder
member Interlace : PngInterlaceOption with get, set
Full name: System.Windows.Media.Imaging.PngBitmapEncoder
--------------------
PngBitmapEncoder() : unit
inherit BitmapSource
member BaseUri : Uri with get, set
member ColorContexts : ReadOnlyCollection<ColorContext>
member CreateInPlaceBitmapMetadataWriter : unit -> InPlaceBitmapMetadataWriter
member Decoder : BitmapDecoder
member Thumbnail : BitmapSource
static member Create : bitmapUri:Uri -> BitmapFrame + 8 overloads
Full name: System.Windows.Media.Imaging.BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapStream: Stream) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapUri: Uri) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(source: BitmapSource, thumbnail: BitmapSource) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapUri: Uri, uriCachePolicy: Net.Cache.RequestCachePolicy) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapStream: Stream, createOptions: BitmapCreateOptions, cacheOption: BitmapCacheOption) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapUri: Uri, createOptions: BitmapCreateOptions, cacheOption: BitmapCacheOption) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(source: BitmapSource, thumbnail: BitmapSource, metadata: BitmapMetadata, colorContexts: Collections.ObjectModel.ReadOnlyCollection<ColorContext>) : BitmapFrame
(+0 other overloads)
BitmapFrame.Create(bitmapUri: Uri, createOptions: BitmapCreateOptions, cacheOption: BitmapCacheOption, uriCachePolicy: Net.Cache.RequestCachePolicy) : BitmapFrame
(+0 other overloads)
BitmapSource.Create(pixelWidth: int, pixelHeight: int, dpiX: float, dpiY: float, pixelFormat: PixelFormat, palette: BitmapPalette, pixels: Array, stride: int) : BitmapSource
(+0 other overloads)
static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
static member AppendAllText : path:string * contents:string -> unit + 1 overload
static member AppendText : path:string -> StreamWriter
static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
static member Create : path:string -> FileStream + 3 overloads
static member CreateText : path:string -> StreamWriter
static member Decrypt : path:string -> unit
static member Delete : path:string -> unit
static member Encrypt : path:string -> unit
static member Exists : path:string -> bool
...
Full name: System.IO.File
File.Create(path: string, bufferSize: int) : FileStream
File.Create(path: string, bufferSize: int, options: FileOptions) : FileStream
File.Create(path: string, bufferSize: int, options: FileOptions, fileSecurity: Security.AccessControl.FileSecurity) : FileStream
type Plot =
new : geom:Geometry -> Plot
member SaveAsBitmap : fileName:string -> unit
Full name: Plot-geometry.Plot
Plots an OGR.Geometry on a Xaml Window
--------------------
new : geom:OGR.Geometry -> Plot
Full name: Microsoft.FSharp.Core.Operators.max
type Window =
inherit ContentControl
new : unit -> Window
member Activate : unit -> bool
member AllowsTransparency : bool with get, set
member Close : unit -> unit
member DialogResult : Nullable<bool> with get, set
member DragMove : unit -> unit
member Hide : unit -> unit
member Icon : ImageSource with get, set
member IsActive : bool
member Left : float with get, set
...
Full name: System.Windows.Window
--------------------
Window() : unit
Full name: Plot-geometry.Plot.SaveAsBitmap