Friday, November 15, 2013

Creating XAML hexagons without using a PATH element

I was recently working on a small Windows Phone 8 app that needed some tessellated (tiled) hexagons and after searching the web for a simple solution, I did not find what I wanted. 

All of the solutions involved drawing the hexagon using drawing primitives such as the PATH element.  I wanted a “simpler” solution.  I wanted a Grid based solution, and here it is.

To start with I needed to know two semi-basic points about hexagons: what is the ratio of height to width, and (with the hex “standing” on one of its flat sides) what is the the ratio between the horizontal length of the flat and the horizontal distance from the end of the flat side to the edge of the hexagon.  (Boy that is harder to write than it is to just see it)

I found both pieces of information at: Hexnet

Hexnet shows that if the length of one side of a hex has a length of 1, then the overall width is 2 and the height of the hexagon is √3 (approx. 1.73).  So, if we were to build this in a grid, we would have a single hexagon take up 6 cells (2 rows and 3 columns) and our two critical semi-basic points are: √3 to 2 and 1 to .5.

If we wanted a hexagon with an overall width of 200px (200 times our example above), our grid would be defined as:

   1:  <Grid x:Name="LayoutRoot" Background="White" Width="200" Height="173">
   2:      <Grid.ColumnDefinitions>
   3:          <ColumnDefinition Width="*"></ColumnDefinition>
   4:          <ColumnDefinition Width="2*"></ColumnDefinition>
   5:          <ColumnDefinition Width="*"></ColumnDefinition>
   6:      </Grid.ColumnDefinitions>
   7:      <Grid.RowDefinitions>
   8:          <RowDefinition></RowDefinition>
   9:          <RowDefinition></RowDefinition>
  10:      </Grid.RowDefinitions>
  11:  </Grid>



if you look at this grid with gridlines on, you get:


image



Now from here we can either create a outline of a hexagon using 6 line objects, create a solid hexagon using 3 rectangle objects or combine both for an outlined solid color hexagon.


“Wait!”, you say.  “I can see the six lines making up the outline of a hexagon, but how could you do a solid color hexagon with three squares?”


Well, I’m glad you asked.  If you fill the center column with a rectangle, that’s one.  If you make a copy but rotate it 60 degrees using the center as the pivot point and make a third and rotate it –60 degrees then you have your solid color hexagon.


And, if you just start repeating the second and third columns when you add columns, you can start to create a grid full of tessellated (tiled) hexagons, just like I did in this image.


image


And here is the complete xaml I used to create the above image (From this code it was simple to extract rules that I used to create large fields of tessellated (tiled) hexagons in code):


   1:  <UserControl x:Class="Hexagon.MainPage"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:      mc:Ignorable="d"
   7:      d:DesignHeight="346" d:DesignWidth="500">
   8:      <Viewbox Stretch="Uniform">
   9:          <Grid x:Name="LayoutRoot" Background="White" Width="500" Height="346" Margin="50">
  10:              <Grid.ColumnDefinitions>
  11:                  <ColumnDefinition Width="*"></ColumnDefinition>
  12:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  13:                  <ColumnDefinition Width="*"></ColumnDefinition>
  14:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  15:                  <ColumnDefinition Width="*"></ColumnDefinition>
  16:                  <ColumnDefinition Width="2*"></ColumnDefinition>
  17:                  <ColumnDefinition Width="*"></ColumnDefinition>
  18:              </Grid.ColumnDefinitions>
  19:              <Grid.RowDefinitions>
  20:                  <RowDefinition></RowDefinition>
  21:                  <RowDefinition></RowDefinition>
  22:                  <RowDefinition></RowDefinition>
  23:                  <RowDefinition></RowDefinition>
  24:              </Grid.RowDefinitions>
  25:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2"></Rectangle>
  26:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2">
  27:                  <Rectangle.RenderTransform>
  28:                      <RotateTransform Angle="-60" />
  29:                  </Rectangle.RenderTransform>
  30:              </Rectangle>
  31:              <Rectangle Fill="Pink" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.RowSpan="2">
  32:                  <Rectangle.RenderTransform>
  33:                      <RotateTransform Angle="60" />
  34:                  </Rectangle.RenderTransform>
  35:              </Rectangle>
  36:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2"></Rectangle>
  37:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2">
  38:                  <Rectangle.RenderTransform>
  39:                      <RotateTransform Angle="-60" />
  40:                  </Rectangle.RenderTransform>
  41:              </Rectangle>
  42:              <Rectangle Fill="Aquamarine" RenderTransformOrigin="0.5, 0.5" Grid.Column="3" Grid.Row="1" Grid.RowSpan="2">
  43:                  <Rectangle.RenderTransform>
  44:                      <RotateTransform Angle="60" />
  45:                  </Rectangle.RenderTransform>
  46:              </Rectangle>
  47:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2"></Rectangle>
  48:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2">
  49:                  <Rectangle.RenderTransform>
  50:                      <RotateTransform Angle="-60" />
  51:                  </Rectangle.RenderTransform>
  52:              </Rectangle>
  53:              <Rectangle Fill="LightBlue" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="2" Grid.RowSpan="2">
  54:                  <Rectangle.RenderTransform>
  55:                      <RotateTransform Angle="60" />
  56:                  </Rectangle.RenderTransform>
  57:              </Rectangle>
  58:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2"></Rectangle>
  59:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
  60:                  <Rectangle.RenderTransform>
  61:                      <RotateTransform Angle="-60" />
  62:                  </Rectangle.RenderTransform>
  63:              </Rectangle>
  64:              <Rectangle Fill="LemonChiffon" RenderTransformOrigin="0.5, 0.5" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2">
  65:                  <Rectangle.RenderTransform>
  66:                      <RotateTransform Angle="60" />
  67:                  </Rectangle.RenderTransform>
  68:              </Rectangle>
  69:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2"></Rectangle>
  70:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
  71:                  <Rectangle.RenderTransform>
  72:                      <RotateTransform Angle="-60" />
  73:                  </Rectangle.RenderTransform>
  74:              </Rectangle>
  75:              <Rectangle Fill="Thistle" RenderTransformOrigin="0.5, 0.5" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
  76:                  <Rectangle.RenderTransform>
  77:                      <RotateTransform Angle="60" />
  78:                  </Rectangle.RenderTransform>
  79:              </Rectangle>
  80:              <Line Grid.Column="0" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  81:              <Line Grid.Column="1" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  82:              <Line Grid.Column="2" Grid.Row="0" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  83:              <Line Grid.Column="0" Grid.Row="1" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  84:              <Line Grid.Column="1" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  85:              <Line Grid.Column="2" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  86:              <Line Grid.Column="3" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  87:              <Line Grid.Column="4" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  88:              <Line Grid.Column="5" Grid.Row="0" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  89:              <Line Grid.Column="6" Grid.Row="0" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  90:              <Line Grid.Column="4" Grid.Row="1" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  91:              <Line Grid.Column="5" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  92:              <Line Grid.Column="6" Grid.Row="1" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  93:              <Line Grid.Column="0" Grid.Row="2" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  94:              <Line Grid.Column="2" Grid.Row="2" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  95:              <Line Grid.Column="0" Grid.Row="3" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  96:              <Line Grid.Column="1" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  97:              <Line Grid.Column="2" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  98:              <Line Grid.Column="3" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Top" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
  99:              <Line Grid.Column="4" Grid.Row="2" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 100:              <Line Grid.Column="6" Grid.Row="2" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 101:              <Line Grid.Column="4" Grid.Row="3" X1="1" Y1="1" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 102:              <Line Grid.Column="5" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="0" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" VerticalAlignment="Bottom" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 103:              <Line Grid.Column="6" Grid.Row="3" X1="1" Y1="0" X2="0" Y2="1" Margin="-5 -5" StrokeThickness="10" Stretch="Fill" Stroke="Black" StrokeEndLineCap="Round" StrokeStartLineCap="Round"></Line>
 104:          </Grid>
 105:      </Viewbox>
 106:  </UserControl>

Tuesday, November 12, 2013

My adventures in Windows Phone 8 development

A couple of months ago, I attended VSLive in Redmond.  While I was there I sat in on a session on Windows Phone 8 Development given by Nick Landry ( @ActiveNick ). 

Since then I’ve signed up for a Windows Phones Developers Account ( Beer & Pretzel Games ), a DVLUP.com account ( My saunderl account ) and have published 3 apps (Tic Tac Toe, Sudoku Challenge and Simple Lap Counter).  None of these apps are going to set the world on fire, but it is a start and I’ve got a list of about twenty other apps and games I want to write.

So, for at least the next few posts, I will be writing about my adventures in Windows Phone 8 development.

Thursday, February 23, 2012

I’m a 5.8 out of 6 programmer

If you go to How to recongnise a good programmer, you will see one man’s idea of how to spot a good programmer.  When looking around the web, I stumbled upon this conversation about it.  The last post tried to adapt this to diesel mechanics.  I’ve added my comments in red to the post, since I think the poster does not have a clue what a programmer does.  Maybe I can enlighten him a bit. (I’ve also colored his adaptation in blue.
Let's see how it applies to my business model.
I have a fleet of eighteen wheelers and I need to hire a bunch of mechanics to service Volvo, Kenworth and Mack trucks.

Wow, to compare mechanics to programmers in the first place ... this guy hasn't a clue what a programmer does.  But, just to play along lets see how this works out
The article gives me two possible hiring scenarios which I've adapted to my business.
Positive indicators:
Passionate about technology
Heard about the latest F1 regenerative energy systems.
No, how about more like "Really likes to work on Trucks"?
 
Programs as a hobby
Tinkers with his own dirt bike.
<Sigh> I can see he just does not get it.  More like: Loves to work on Trucks so will do it on his/her own time. 
Will talk your ear off on a technical subject if encouraged
NASCAR galore.
 If you think NASCAR is a technical subject in you field then you will quickly be out of business.
  
Significant (and often numerous) personal side-projects over the years
Remember his Radio-Flyer cart !Amazing how poorly you build your straw man!  If I applied this to mechanics, I would say "Has always had grease under his fingernails." or maybe "Has rebuilt many different Trucks starting in High school"
  
Learns new technologies on his/her own
Reads "Popular Mechanics" magazine. WTF! You really believe you can learn new technologies in "Popular Mechanics"?  There is no way you can run a successful company ... Ok, I'll continue to play along.  If I applied this to Truck mechanics, I would say "Keeps himself trained on the latest engine designs.  Learns about all popular engine modifications."
Opinionated about which technologies are better for various usages
He's keen on Brembo brakes.
OK, I'll assume you know the difference between technologies and products, right?  This is where some of your analogy starts to break down. When was there a major new development in internal combustion engine design?  Basic diesel technology is how old?
Very uncomfortable about the idea of working with a technology he doesn't believe to be “right”
Hates the old carburetor thing.
So you think that a great diesel mechanic would love to get a job with you working on your "Water and Chicken poop powered" Trucks?
 
Clearly smart, can have great conversations on a variety of topics
iTune, iPhone, Roberta Black, Iraq etc.
Another place that this analogy breaks down.  <Sigh> I'll just keep quiet on this one.
 
Started programming long before university/work
As a teenager repaired the toaster and changed the kitchen faucet.More like, knew what a torque wrench was before he started his first mechanics class.  
Has some hidden “icebergs”, large personal projects under the CV radar
Wants to tinker with a jet ski watercraft. Close, more like, knows how to alter a jet ski engine to get a 50% power boost without damaging the engine.
 
Knowledge of a large variety of unrelated technologies (may not be on CV)
Knows the difference between a CD, a regular DVD and a blue-ray DVD.If you are not being deliberately stupid, then <sigh> I’ll just keep quiet.
Negative indicators:
Programming is a day job
Does truck service & repairs for a living.
More like "Never turns a wrench unless he is paid to, and even then he bitched about it.  Why does he do it - its a paycheck."
  
Don’t really want to “talk shop”, even when encouraged to
Prefers to check the service manuals and do the job at hand.
Here you have is completely backward.  This is a prime example of "Learns new technologies on his/her own" above.  Instead, the correct example would be, "Never wants to learn the tips and tricks of other experts, but would rather scratch his ass and complain about the pay"
 
Learns new technologies in company-sponsored courses
If I am going to send him to a GM training course he will gladly obliged.
Nope, more like "Hey Bob, we are going to expand and start working on FIAT's.  The Community College is offering night courses." and Bob replies, "Screw you boss, if you want me to go, it's during work hours, your paying and I'm not going to make up the time."
 
Happy to work with whatever technology you’ve picked, “all technologies are good”
If we decide to buy GM trucks he will gladly work on them
GM trucks? No more like now your going to work on HVAC systems and by-god they had better be as good at is as they were at diesels. 
Doesn’t seem too smart
He does not seem interested in iTune, iPhone, Roberta Black, Iraq etc.
Another place that this analogy breaks down.  <Sigh> I'll just keep quiet on this one.
  
Started programming at university
Learned how trucks are built, how to service them and had hands on practical experience under the supervision of master mechanics in an accredited school with his major in Volvo engine and control module diagnostic and repair and minor in Kenworth engine and transmission repair and has a "specialist" certification.
Another place that this analogy breaks down, but I'll give it a try.  First time the future mechanic ever heard of a ratchet wrench when he got the list of required tools for his new degree. If we were to equate a CS degree to a tech degree and certification, it the tech degree and certification would guarantee that the student has shown that he knows exactly what each tool is, how it is used and if necessary, how to make one from scratch. 
All programming experience is on the CV
Left out his alma-mater racing club where he is the chief mechanic.
<sigh>
 
Focused mainly on one or two technology stacks (e.g. everything to do with developing a java application), with no experience outside of it
He is focused on Volvo and Kenworth and has really no experience with Tatra, Zim, Hino, FIAT and other trucks.
Almost right, if the other types of trucks used different types of engines built with different materials and you needed a completely different set of tools that the mechanic would have no idea how to use.
I don't know why, but I would hire the guy/gal with the negative indicators. Lucian
Well, Lucian, what your saying is that you would rather have a person that only learned what a wrench is after he started school, only does the work because he is getting a paycheck, doesn't even like talking about what he does, refuses to learn anything unless he is paid to do it and thinks that he is equally skilled at working on HVAC as he is on a diesel engine because "All technologies are good"?
Wow, I give your company 6 to 8 weeks before either the "mechanics" you hire starts your building on fire, or you are sued out of business because a "mechanic" put Mack parts on a Kenworth. (remember, all technology is good, right?)
This is why comparing a mechanic (a job where there is always only one way that things go together) and a programmer (a job where there are literally a million ways to do things.  Most of them the wrong way, but quite a few almost correct if not equally correct.)
When every Trucking company builds there own engines, changes the type of engine every couple of years, fixing the engine can be done 1000 different ways, and require the mechanics to use a whole different set of tools for each new type, then we can START to compare diesel truck mechanics to programmers.