Added continent colors to template system
authorW. Trevor King <wking@drexel.edu>
Sun, 28 Mar 2010 00:43:58 +0000 (20:43 -0400)
committerW. Trevor King <wking@drexel.edu>
Sun, 28 Mar 2010 00:43:58 +0000 (20:43 -0400)
pyrisk/graphics.py
share/templates/earth/colors.ccl [new file with mode: 0644]

index f171e0d..38d58ca 100644 (file)
@@ -24,15 +24,16 @@ import operator
 import os
 import os.path
 
-from .base import ID_CmpMixin
+from .base import NameMixin, ID_CmpMixin
 
 
-class Template (object):
+class Template (NameMixin):
     """Setup regions for a particular world.
     """
-    def __init__(self, name, regions):
-        self.name = name
+    def __init__(self, name, regions, continent_colors={}):
+        NameMixin.__init__(self, name)
         self.regions = regions
+        self.continent_colors = continent_colors
 
 class TemplateLibrary (object):
     """Create Templates on demand from a directory of template data.
@@ -42,10 +43,11 @@ class TemplateLibrary (object):
     def __init__(self, template_dir='share/templates/'):
         self.template_dir = os.path.abspath(os.path.expanduser(template_dir))
     def get(self, name):
-        region_pointlists,route_pointlists = self._get_pointlists(name)
-        template = self._generate_template(region_pointlists, route_pointlists)
-        return template
-    def _get_pointlists(self, name):
+        region_pointlists,route_pointlists,continent_colors = \
+            self._get_data(name)
+        regions = self._generate_regions(region_pointlists, route_pointlists)
+        return Template('template', regions, continent_colors)
+    def _get_data(self, name):
         dirname = os.path.join(self.template_dir, name.lower())
         try:
             files = os.listdir(dirname)
@@ -57,12 +59,14 @@ class TemplateLibrary (object):
             path = os.path.join(dirname, filename)
             name,extension = filename.rsplit('.', 1)
             if extension == 'reg':
-                region_pointlists[name] = self._read_file(path)
+                region_pointlists[name] = self._read_pointlist(path)
             elif extension in ['rt', 'vrt']:
-                route_pointlists[name] = (self._read_file(path),
+                route_pointlists[name] = (self._read_pointlist(path),
                                           extension == 'vrt')
-        return (region_pointlists, route_pointlists)
-    def _read_file(self, filename):
+            elif extension == 'ccl':
+                continent_colors = self._read_colors(path)
+        return (region_pointlists, route_pointlists, continent_colors)
+    def _read_pointlist(self, filename):
         pointlist = []
         for line in open(filename, 'r'):
             line = line.strip()
@@ -78,7 +82,17 @@ class TemplateLibrary (object):
                 label = None
             pointlist.append((x,y,label))
         return pointlist
-    def _generate_template(self, region_pointlists, route_pointlists):
+    def _read_colors(self, filename):
+        colors = {}
+        for line in open(filename, 'r'):
+            line = line.strip()
+            if len(line) == 0:
+                continue
+            fields = line.split('\t')
+            name,color = fields
+            colors[name] = color
+        return colors
+    def _generate_regions(self, region_pointlists, route_pointlists):
         regions = []
         all_boundaries = []
         for name,pointlist in region_pointlists.items():
@@ -107,7 +121,7 @@ class TemplateLibrary (object):
         match_counts = [b.match_count for b in all_boundaries]
         assert min(match_counts) in [0, 1], set(match_counts)
         assert max(match_counts) == 1, set(match_counts)
-        return Template('template', regions)
+        return regions
     def _pointlist_to_array_of_boundaries(self, all_boundaries, pointlist):
         boundaries = []
         head_to_tail = []
@@ -245,7 +259,14 @@ class Boundary (ID_CmpMixin, list):
         self.y_min = min([p[1] for p in self])
         self.y_max = max([p[1] for p in self])
 
-class Region (ID_CmpMixin, list):
+class Route (ID_CmpMixin):
+    """Connect non-adjacent Regions.
+    """
+    def __init__(self, boundary):
+        ID_CmpMixin.__init__(self)
+        self.boundary = boundary
+
+class Region (NameMixin, ID_CmpMixin, list):
     """Contains a list of boundaries and a label.
 
     Regions can be Territories, sections of ocean, etc.
@@ -262,12 +283,12 @@ class Region (ID_CmpMixin, list):
     """
     def __init__(self, name, boundaries, head_to_tail, routes=None,
                  route_head_to_tail=None, label_offset=(0,0)):
+        NameMixin.__init__(self, name)
         list.__init__(self, boundaries)
         ID_CmpMixin.__init__(self)
         for boundary in self:
             boundary.regions.append(self)
         self.head_to_tail = head_to_tail
-        self.name = name
         self.routes = routes
         self.route_head_to_tail = route_head_to_tail
         if routes == None:
@@ -302,7 +323,7 @@ class Region (ID_CmpMixin, list):
             self.starts.append(pos)
             for p in new:
                 points.append(pos+p)
-        assert points[-1] == points[0], '%s: %s' % (self.name, points)
+        assert points[-1] == points[0], '%s: %s' % (self, points)
         self.outline = points
     def locate_routes(self):
         self.route_starts = []
@@ -316,14 +337,6 @@ class Region (ID_CmpMixin, list):
                     self.route_starts.append(point-nameless(anchor))
                     break
 
-class Route (ID_CmpMixin):
-    """Connect non-adjacent Regions.
-    """
-    def __init__(self, boundary):
-        ID_CmpMixin.__init__(self)
-        self.boundary = boundary
-
-
 class WorldRenderer (object):
     def __init__(self, template_lib=None, line_width=2, buf=10, dpcm=60):
         self.template_lib = template_lib
@@ -348,14 +361,16 @@ class WorldRenderer (object):
             % (float(width)/self.dpcm, float(height)/self.dpcm,
                width, height),
             '     xmlns="http://www.w3.org/2000/svg" version="1.1">',
-            '<desc>PyRisk world: %s</desc>' % template.name,
+            '<desc>PyRisk world: %s</desc>' % template,
             ]
         drawn_rts = {}
         for r in template.regions:
+            t = self._matching_territory(world, r)
+            c_col = template.continent_colors[t.continent.name]
             lines.extend([
-                    '<!-- %s -->' % r.name,
-                    '<polygon fill="red" stroke="%s" stroke-width="%d"'
-                    % (self.line_color, self.line_width),
+                    '<!-- %s -->' % r,
+                    '<polygon fill="%s" stroke="%s" stroke-width="%d"'
+                    % (c_col, self.line_color, self.line_width),
                     '         points="%s" />'
                     % ' '.join(['%d,%d' % ((region_pos[id(r)]+p)
                                            *(1,-1) # svg y value increases down
@@ -430,6 +445,22 @@ class WorldRenderer (object):
         for key,value in region_pos.items():
             region_pos[key] = value - Vector((x_min, y_min))
         return (region_pos, x_max-x_min, y_max-y_min)
+    def _matching_territory(self, world, region):
+        t = None
+        try:
+            t = world.territory_by_name(region.name)
+        except KeyError:
+            for rt in region.routes:
+                if not rt.virtual:
+                    continue
+                for r in rt.regions:
+                    try:
+                        t = world.territory_by_name(r.name)
+                    except KeyError:
+                        pass
+        assert t != None, 'No territory in %s associated with region %s' \
+            % (world, region)
+        return t
     def _auto_template(self, world):
         raise NotImplementedError
 
diff --git a/share/templates/earth/colors.ccl b/share/templates/earth/colors.ccl
new file mode 100644 (file)
index 0000000..7b935ab
--- /dev/null
@@ -0,0 +1,6 @@
+North America  yellow
+Europe blue
+Asia   green
+South America  red
+Africa orange
+Australia      purple