diff --git a/lib/xmet/hodograph.py b/lib/xmet/hodograph.py
index d1c3c2b..963cd08 100644
--- a/lib/xmet/hodograph.py
+++ b/lib/xmet/hodograph.py
@@ -8,7 +8,7 @@ WIND_SPEED_MAX  = 140 # knots
 WIND_SPEED_MIN  =  10
 WIND_SPEED_STEP =  10
 
-WIND_DIR_STEP = 90 # degrees
+WIND_DIR_STEP = 45 # degrees
 
 def radians(degrees: float) -> float:
     return (degrees + 90) * (math.pi / 180.0)
@@ -21,72 +21,54 @@ def knots(ms: float) -> float:
 
 class Hodograph():
     def __init__(self, width, height):
-        self.zoom     = 1.2
-        self.offset_x = 0.1 # Percentage of the upper left quadrant rendered
-        self.offset_y = 0.9 # Percentage of the upper right quadrant rendered
-
-        self.min_x = 0
-        self.min_y = 0
-        self.max_x = 0
-        self.max_y = 0
-
-        self.width  = min(width, height)
-        self.height = min(width, height)
-        self.radius = min(width, height) * self.zoom
-
-    def sample_to_graph(self, wind_speed: dir, wind_dir: float) -> tuple:
-        r = self.radius * (wind_speed / WIND_SPEED_MAX)
-
-        x = r * math.cos(radians(wind_dir))
-        y = r * math.sin(radians(wind_dir))
-
-        return x, y
+        self.width   = min(width, height)
+        self.height  = min(width, height)
+        self.radius  = min(width, height) / 2
+        self.extents = None
 
     def sample_to_screen(self, wind_speed: dir, wind_dir: float) -> tuple:
-        gx, gy = self.sample_to_graph(wind_speed, wind_dir)
+        r = self.radius * (wind_speed / WIND_SPEED_MAX)
 
-        return (
-            self.offset_x * self.width  + gx,
-            self.offset_y * self.height + gy
-        )
+        x = self.radius + r * math.cos(radians(wind_dir))
+        y = self.radius + r * math.sin(radians(wind_dir))
 
-    def find_extents(self, sounding: Sounding):
-        """
-        Determine the boundaries of the sounding to set the center and zoom
-        appropriately.
-        """
-        for sample in sounding.samples:
-            x, y = self.sample_to_graph(sample.wind_speed, sample.wind_dir)
+        if self.extents is None:
+            return x, y
+        else:
+            min_x, min_y = self.extents['min']
+            max_x, max_y = self.extents['max']
 
-            if self.min_x > x:
-                self.min_x = x
+            box_width  = max_x - min_x
+            box_height = max_y - min_y
+            box        = max(box_width, box_height)
 
-            if self.min_y > y:
-                self.min_y = y
+            offset_x = self.width  * ((box - box_width)  / box) / 2
+            offset_y = self.height * ((box - box_height) / box) / 2
 
-            if self.max_x < x:
-                self.max_x = x
-
-            if self.max_y < y:
-                self.max_y = y
-
-        self.offset_x = self.min_x / self.radius + 0.1
-        self.offset_y = (self.radius - self.max_y) / self.radius
-        self.zoom     = min(self.width, self.height) / max(self.max_x - self.min_x,
-                            self.max_y - self.min_y) / 2
-        self.radius = min(self.width, self.height) * self.zoom
+            return (
+                offset_x + ((x - min_x) / box) * self.width,
+                offset_y + ((y - min_y) / box) * self.height
+            )
 
     def draw_speed_lines(self, cr: cairo.Context, x, y):
         cr.save()
 
         cr.set_source_rgb(0.5, 0.5, 0.5)
         cr.set_line_width(0.5)
-        cr.set_dash([5, 5], 1)
 
-        for speed in range(WIND_SPEED_MIN, WIND_SPEED_MAX+1, WIND_SPEED_STEP):
-            cr.arc(x + self.offset_x * self.width,
-                   y + self.offset_y * self.height,
-                   self.radius * min(speed, WIND_SPEED_MAX) / WIND_SPEED_MAX,
+        cx, cy = self.sample_to_screen(0, 0)
+
+        for speed in range(WIND_SPEED_MIN, 2*WIND_SPEED_MAX, WIND_SPEED_STEP):
+            if speed % (WIND_SPEED_STEP*2) == 0:
+                cr.set_dash([1, 1], 0)
+            else:
+                cr.set_dash([5, 5], 1)
+
+            sx, sy = self.sample_to_screen(speed, 0)
+
+            cr.arc(x + cx,
+                   x + cy,
+                   sy - self.radius,
                    0,
                    2*math.pi)
 
@@ -98,10 +80,16 @@ class Hodograph():
         cr.save()
 
         cr.set_source_rgb(0.5, 0.5, 0.5)
+        cr.set_line_width(0.5)
 
         for angle in range(0, 360+1, WIND_DIR_STEP):
-            sx1, sy1 = self.sample_to_screen(WIND_SPEED_MAX, angle)
-            sx2, sy2 = self.sample_to_screen(WIND_SPEED_MAX, angle + 180)
+            sx1, sy1 = self.sample_to_screen(2*WIND_SPEED_MAX, angle)
+            sx2, sy2 = self.sample_to_screen(2*WIND_SPEED_MAX, angle + 180)
+
+            if angle % 90 == 0:
+                cr.set_dash([1, 1], 0)
+            else:
+                cr.set_dash([5, 5], 1)
 
             cr.move_to(x + sx1, y + sy1)
             cr.line_to(x + sx2, y + sy2)
@@ -112,19 +100,14 @@ class Hodograph():
     def draw_speed_legends(self, cr: cairo.Context, x, y):
         cr.save()
 
-        x_offset_scale = 0.01190476
-        y_offset_scale = 0.01
-
-        x_offset = x_offset_scale * self.radius
-        y_offset = y_offset_scale * self.radius
-
         for speed in range(WIND_SPEED_MIN, WIND_SPEED_MAX, WIND_SPEED_STEP):
             text    = "%dkt" % speed
             extents = cr.text_extents(text)
 
             sx, sy = self.sample_to_screen(speed, 180)
 
-            cr.move_to(x + sx + x_offset, y + sy - y_offset)
+            cr.move_to(x + sx + extents.width * 0.25,
+                       y + sy - extents.height * 1.5)
             cr.show_text(text)
             cr.stroke()
 
@@ -142,6 +125,54 @@ class Hodograph():
             if height < key:
                 return self.COLORS[key]
 
+    def each_significant_sample(self, sounding: Sounding):
+        for sample in sounding.samples:
+            if sample.pressure < 0 or sample.pressure is None:
+                continue
+
+            if sample.height is None:
+                continue
+
+            if self.color(sample.height) is None:
+                break
+
+            yield sample
+
+    def find_extents(self, sounding: Sounding):
+        min_x, min_y = None, None
+        max_x, max_y = None, None
+
+        first = True
+
+        for sample in self.each_significant_sample(sounding):
+            sx, sy = self.sample_to_screen(knots(sample.wind_speed),
+                                           sample.wind_dir)
+
+            if first:
+                min_x = sx
+                max_x = sx
+                min_y = sy
+                max_y = sy
+
+                first = False
+            else:
+                if min_x > sx:
+                    min_x = sx
+
+                if min_y > sy:
+                    min_y = sy
+
+                if max_x < sx:
+                    max_x = sx
+
+                if max_y < sy:
+                    max_y = sy
+
+        return {
+            'min': (min_x, min_y),
+            'max': (max_x, max_y)
+        }
+
     def draw_sounding(self,
                       cr: cairo.Context,
                       x,
@@ -154,13 +185,12 @@ class Hodograph():
         sx_last    = None
         sy_last    = None
 
-        for sample in sounding.samples:
-            if sample.pressure < 0 or sample.pressure is None:
-                continue
+        min_x, min_y = self.extents['min']
+        max_x, max_y = self.extents['max']
 
-            if sample.height is None:
-                continue
+        box = max(max_x - min_x, max_y - min_y)
 
+        for sample in self.each_significant_sample(sounding):
             color = self.color(sample.height)
 
             if color is None:
@@ -233,17 +263,17 @@ class Hodograph():
             offset += interval
 
     def draw(self, cr: cairo.Context, x, y, sounding: Sounding):
-        self.find_extents(sounding)
+        self.extents = self.find_extents(sounding)
 
         cr.rectangle(x, y, self.width, self.height)
         cr.clip()
 
-        self.draw_speed_lines(cr, x, y)
         self.draw_direction_lines(cr, x, y)
-
-        self.draw_sounding(cr, x, y, sounding)
+        self.draw_speed_lines(cr, x, y)
 
         self.draw_speed_legends(cr, x, y)
         self.draw_height_legends(cr, x, y)
 
+        self.draw_sounding(cr, x, y, sounding)
+
         cr.reset_clip()