Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1105 lines (1081 sloc) 79.4 KB
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>map.py</title>
<link rel="stylesheet" href="pycco.css">
</head>
<body>
<div id="background"></div>
<div id='container'>
<div class='section'>
<div class='docs'><h1>map.py</h1></div>
</div>
<div class='clearall'>
<div class='section' id='section-0'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-0'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">maplayer</span> <span class="kn">import</span> <span class="n">MapLayer</span>
<span class="kn">from</span> <span class="nn">geometry.utils</span> <span class="kn">import</span> <span class="n">geom_to_bbox</span>
<span class="kn">from</span> <span class="nn">geometry</span> <span class="kn">import</span> <span class="n">BBox</span><span class="p">,</span> <span class="n">View</span>
<span class="kn">from</span> <span class="nn">shapely.geometry.base</span> <span class="kn">import</span> <span class="n">BaseGeometry</span>
<span class="kn">from</span> <span class="nn">shapely.geometry</span> <span class="kn">import</span> <span class="n">Polygon</span>
<span class="kn">from</span> <span class="nn">proj</span> <span class="kn">import</span> <span class="n">projections</span>
<span class="kn">from</span> <span class="nn">filter</span> <span class="kn">import</span> <span class="n">filter_record</span>
<span class="kn">from</span> <span class="nn">errors</span> <span class="kn">import</span> <span class="n">KartographError</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-1'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-1'>#</a>
</div>
<h2>Map</h2>
</div>
<div class='code'>
<div class="highlight"><pre></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-2'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-2'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">Map</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-3'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-3'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">me</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">layerCache</span><span class="p">,</span> <span class="n">format</span><span class="o">=</span><span class="s">&#39;svg&#39;</span><span class="p">,</span> <span class="n">src_encoding</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="n">me</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">options</span>
<span class="n">me</span><span class="o">.</span><span class="n">format</span> <span class="o">=</span> <span class="n">format</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-4'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-4'>#</a>
</div>
<p>List and dictionary references to the map layers.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">layers</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">me</span><span class="o">.</span><span class="n">layersById</span> <span class="o">=</span> <span class="p">{}</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-5'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-5'>#</a>
</div>
<p>We will cache the bounding geometry since we need it twice, eventually.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">_bounding_geometry_cache</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">me</span><span class="o">.</span><span class="n">_unprojected_bounds</span> <span class="o">=</span> <span class="bp">None</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-6'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-6'>#</a>
</div>
<p>The <strong>source encoding</strong> will be used as first guess when Kartograph tries to decode
the meta data of shapefiles etc. We use Unicode as default source encoding.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="ow">not</span> <span class="n">src_encoding</span><span class="p">:</span>
<span class="n">src_encoding</span> <span class="o">=</span> <span class="s">&#39;utf-8&#39;</span>
<span class="n">me</span><span class="o">.</span><span class="n">_source_encoding</span> <span class="o">=</span> <span class="n">src_encoding</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-7'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-7'>#</a>
</div>
<p>Construct <a href="maplayer.py">MapLayer</a> instances for every layer and store references
to the layers in a list and a dictionary.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer_cfg</span> <span class="ow">in</span> <span class="n">options</span><span class="p">[</span><span class="s">&#39;layers&#39;</span><span class="p">]:</span>
<span class="n">layer_id</span> <span class="o">=</span> <span class="n">layer_cfg</span><span class="p">[</span><span class="s">&#39;id&#39;</span><span class="p">]</span>
<span class="n">layer</span> <span class="o">=</span> <span class="n">MapLayer</span><span class="p">(</span><span class="n">layer_id</span><span class="p">,</span> <span class="n">layer_cfg</span><span class="p">,</span> <span class="n">me</span><span class="p">,</span> <span class="n">layerCache</span><span class="p">)</span>
<span class="n">me</span><span class="o">.</span><span class="n">layers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">layer</span><span class="p">)</span>
<span class="n">me</span><span class="o">.</span><span class="n">layersById</span><span class="p">[</span><span class="n">layer_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">layer</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-8'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-8'>#</a>
</div>
<p>Initialize the projection that will be used in this map. This sounds easier than
it is since we need to compute lot's of stuff here.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">proj</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">_init_projection</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-9'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-9'>#</a>
</div>
<p>Compute the bounding geometry for the map.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">bounds_poly</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">_init_bounds</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-10'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-10'>#</a>
</div>
<p>Set up the <a href="geometry/view.py">view</a> which will transform from projected coordinates
(e.g. in meters) to screen coordinates in our map output.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">_get_view</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-11'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-11'>#</a>
</div>
<p>Get the polygon (in fact it's a rectangle in most cases) that will be used
to clip away unneeded geometry unless <em>cfg['export']['crop-to-view']</em> is set to false.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">view_poly</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">_init_view_poly</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-12'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-12'>#</a>
</div>
<p>Load all features that could be visible in each layer. The feature geometries will
be projected and transformed to screen coordinates.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="n">me</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="n">layer</span><span class="o">.</span><span class="n">get_features</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-13'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-13'>#</a>
</div>
<p>In each layer we will join polygons.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">_join_features</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-14'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-14'>#</a>
</div>
<p>Eventually we crop geometries to the map bounding rectangle.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">options</span><span class="p">[</span><span class="s">&#39;export&#39;</span><span class="p">][</span><span class="s">&#39;crop-to-view&#39;</span><span class="p">]</span> <span class="ow">and</span> <span class="n">format</span> <span class="o">!=</span> <span class="s">&#39;kml&#39;</span><span class="p">:</span>
<span class="n">me</span><span class="o">.</span><span class="n">_crop_layers_to_view</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-15'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-15'>#</a>
</div>
<p>Here's where we apply the simplification to geometries.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">_simplify_layers</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-16'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-16'>#</a>
</div>
<p>Also we can crop layers to another layer, useful if we need to limit geological
geometries such as tree coverage to a political boundary of a country.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">_crop_layers</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-17'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-17'>#</a>
</div>
<p>Or subtract one layer from another (or more), for instance to cut out lakes
from political boundaries.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">me</span><span class="o">.</span><span class="n">_subtract_layers</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-18'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-18'>#</a>
</div>
<h3>Initializing the map projection</h3>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_init_projection</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-19'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-19'>#</a>
</div>
<p>Some output formats don't need map projection at all, so
we just return the identity projection.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">format</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;kml&#39;</span><span class="p">,</span> <span class="s">&#39;json&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="n">projections</span><span class="p">[</span><span class="s">&#39;ll&#39;</span><span class="p">]()</span> <span class="c"># use no projection for KML</span>
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-20'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-20'>#</a>
</div>
<p>If either <em>lat0</em> or <em>lon0</em> were set to "auto", we need to
compute a nice center of the projection and update the
projection configuration.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">autoLon</span> <span class="o">=</span> <span class="s">&#39;lon0&#39;</span> <span class="ow">in</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">]</span> <span class="ow">and</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;lon0&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;auto&#39;</span>
<span class="n">autoLat</span> <span class="o">=</span> <span class="s">&#39;lat0&#39;</span> <span class="ow">in</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">]</span> <span class="ow">and</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;lat0&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;auto&#39;</span>
<span class="k">if</span> <span class="n">autoLon</span> <span class="ow">or</span> <span class="n">autoLat</span><span class="p">:</span>
<span class="n">map_center</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__get_map_center</span><span class="p">()</span>
<span class="k">if</span> <span class="n">autoLon</span><span class="p">:</span>
<span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;lon0&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">map_center</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">autoLat</span><span class="p">:</span>
<span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;lat0&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">map_center</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-21'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-21'>#</a>
</div>
<p>Load the projection class, if the id is known.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;id&#39;</span><span class="p">]</span> <span class="ow">in</span> <span class="n">projections</span><span class="p">:</span>
<span class="n">projC</span> <span class="o">=</span> <span class="n">projections</span><span class="p">[</span><span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;id&#39;</span><span class="p">]]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">KartographError</span><span class="p">(</span><span class="s">&#39;projection unknown </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="s">&#39;id&#39;</span><span class="p">])</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-22'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-22'>#</a>
</div>
<p>Populate a dictionary of projection properties that
will be passed to the projection constructor as keyword
arguments.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">p_opts</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">prop</span> <span class="ow">in</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">prop</span> <span class="o">!=</span> <span class="s">&quot;id&quot;</span><span class="p">:</span>
<span class="n">p_opts</span><span class="p">[</span><span class="n">prop</span><span class="p">]</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;proj&#39;</span><span class="p">][</span><span class="n">prop</span><span class="p">]</span>
<span class="k">return</span> <span class="n">projC</span><span class="p">(</span><span class="o">**</span><span class="n">p_opts</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-23'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-23'>#</a>
</div>
<h3>Determining the projection center</h3>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">__get_map_center</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-24'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-24'>#</a>
</div>
<p>To find out where the map will be centered to we need to
know the geographical boundaries.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span>
<span class="n">mode</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;mode&#39;</span><span class="p">]</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;data&#39;</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-25'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-25'>#</a>
</div>
<p>If the bound mode is set to <em>bbox</em> we simply
take the mean latitude and longitude as center.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="s">&#39;bbox&#39;</span><span class="p">:</span>
<span class="n">lon0</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">lat0</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">-</span> <span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-26'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-26'>#</a>
</div>
<p>If the bound mode is set to <em>point</em> we average
over all latitude and longitude coordinates.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">elif</span> <span class="n">mode</span><span class="p">[:</span><span class="mi">5</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;point&#39;</span><span class="p">:</span>
<span class="n">lon0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">lat0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">m</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">for</span> <span class="p">(</span><span class="n">lon</span><span class="p">,</span> <span class="n">lat</span><span class="p">)</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
<span class="n">lon0</span> <span class="o">+=</span> <span class="n">m</span> <span class="o">*</span> <span class="n">lon</span>
<span class="n">lat0</span> <span class="o">+=</span> <span class="n">m</span> <span class="o">*</span> <span class="n">lat</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-27'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-27'>#</a>
</div>
<p>The computationally worst case is the bound mode
<em>polygon</em> since we need to load the shapefile geometry
to compute its center of mass. However, we need
to load it anyway and cache the bounding geometry,
so this comes at low extra cost.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">elif</span> <span class="n">mode</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;poly&#39;</span><span class="p">:</span>
<span class="n">features</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_bounding_geometry</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">features</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">features</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">geom</span><span class="p">,</span> <span class="n">BaseGeometry</span><span class="p">):</span>
<span class="p">(</span><span class="n">lon0</span><span class="p">,</span> <span class="n">lat0</span><span class="p">)</span> <span class="o">=</span> <span class="n">features</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">geom</span><span class="o">.</span><span class="n">representative_point</span><span class="p">()</span><span class="o">.</span><span class="n">coords</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">lon0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">lat0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">&quot;unrecognized bound mode&quot;</span><span class="p">,</span> <span class="n">mode</span>
<span class="k">return</span> <span class="p">(</span><span class="n">lon0</span><span class="p">,</span> <span class="n">lat0</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-28'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-28'>#</a>
</div>
<h3>Compute the projected bounding box</h3>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_init_bounds</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-29'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-29'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">format</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;kml&#39;</span><span class="p">,</span> <span class="s">&#39;json&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">None</span> <span class="c"># no bounds needed for KML</span>
<span class="kn">from</span> <span class="nn">geometry.utils</span> <span class="kn">import</span> <span class="n">bbox_to_polygon</span>
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span>
<span class="n">proj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">proj</span>
<span class="n">mode</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;mode&#39;</span><span class="p">][:]</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;data&#39;</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-30'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-30'>#</a>
</div>
<p>If the bound mode is set to <em>bbox</em> we simply project
a rectangle in lat/lon coordinates.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="s">&quot;bbox&quot;</span><span class="p">:</span> <span class="c"># catch special case bbox</span>
<span class="n">sea</span> <span class="o">=</span> <span class="n">proj</span><span class="o">.</span><span class="n">bounding_geometry</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">projected</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">sbbox</span> <span class="o">=</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">sea</span><span class="p">)</span>
<span class="n">sbbox</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="n">sbbox</span><span class="o">.</span><span class="n">width</span> <span class="o">*</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;padding&#39;</span><span class="p">])</span>
<span class="k">return</span> <span class="n">bbox_to_polygon</span><span class="p">(</span><span class="n">sbbox</span><span class="p">)</span>
<span class="n">bbox</span> <span class="o">=</span> <span class="n">BBox</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-31'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-31'>#</a>
</div>
<p>If the bound mode is set to <em>points</em> we project all
points and compute the bounding box.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">mode</span><span class="p">[:</span><span class="mi">5</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;point&quot;</span><span class="p">:</span>
<span class="k">for</span> <span class="n">lon</span><span class="p">,</span> <span class="n">lat</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
<span class="n">pt</span> <span class="o">=</span> <span class="n">proj</span><span class="o">.</span><span class="n">project</span><span class="p">(</span><span class="n">lon</span><span class="p">,</span> <span class="n">lat</span><span class="p">)</span>
<span class="n">bbox</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">pt</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-32'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-32'>#</a>
</div>
<p>In bound mode <em>polygons</em>, which should correctly be
named gemetry, we compute the bounding boxes of every
geometry. We will also.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">mode</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;poly&quot;</span><span class="p">:</span>
<span class="n">features</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_bounding_geometry</span><span class="p">()</span>
<span class="n">ubbox</span> <span class="o">=</span> <span class="n">BBox</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">features</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">for</span> <span class="n">feature</span> <span class="ow">in</span> <span class="n">features</span><span class="p">:</span>
<span class="n">ubbox</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">feature</span><span class="o">.</span><span class="n">geometry</span><span class="p">))</span>
<span class="n">feature</span><span class="o">.</span><span class="n">project</span><span class="p">(</span><span class="n">proj</span><span class="p">)</span>
<span class="n">fbbox</span> <span class="o">=</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">feature</span><span class="o">.</span><span class="n">geometry</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="s">&quot;min-area&quot;</span><span class="p">])</span>
<span class="n">bbox</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">fbbox</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-33'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-33'>#</a>
</div>
<p>Save the unprojected bounding box for later to
determine what features can be skipped.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_unprojected_bounds</span> <span class="o">=</span> <span class="n">ubbox</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">KartographError</span><span class="p">(</span><span class="s">&#39;no features found for calculating the map bounds&#39;</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-34'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-34'>#</a>
</div>
<p>If we need some extra geometry around the map bounds, we inflate
the bbox according to the set <em>padding</em>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">bbox</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="n">bbox</span><span class="o">.</span><span class="n">width</span> <span class="o">*</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">]</span> <span class="p">[</span><span class="s">&#39;padding&#39;</span><span class="p">])</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-35'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-35'>#</a>
</div>
<p>At the end we convert the bounding box to a Polygon because
we need it for clipping tasks.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">return</span> <span class="n">bbox_to_polygon</span><span class="p">(</span><span class="n">bbox</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-36'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-36'>#</a>
</div>
<h3>Get bounding geometry</h3>
<p>For bounds mode "<em>polygons</em>" this helper function
returns a list of all geometry that the map should
be cropped to.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_get_bounding_geometry</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-37'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-37'>#</a>
</div>
<p>Use the cached geometry, if available.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_bounding_geometry_cache</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_bounding_geometry_cache</span>
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span>
<span class="n">features</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&#39;bounds&#39;</span><span class="p">][</span><span class="s">&#39;data&#39;</span><span class="p">]</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;layer&#39;</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-38'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-38'>#</a>
</div>
<p>Check that the layer exists.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="nb">id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layersById</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">KartographError</span><span class="p">(</span><span class="s">&#39;layer not found &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="nb">id</span><span class="p">)</span>
<span class="n">layer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">layersById</span><span class="p">[</span><span class="nb">id</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-39'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-39'>#</a>
</div>
<p>Construct the filter function of the layer, which specifies
what features should be excluded from the map completely.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;filter&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">layerFilter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">a</span><span class="p">:</span> <span class="bp">True</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">layerFilter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">rec</span><span class="p">:</span> <span class="n">filter_record</span><span class="p">(</span><span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;filter&#39;</span><span class="p">],</span> <span class="n">rec</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-40'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-40'>#</a>
</div>
<p>Construct the filter function of the boundary, which specifies
what features should be excluded from the boundary calculation.
For instance, you often want to exclude Alaska and Hawaii from
the boundary computation of the map, although a part of Alaska
might be visible in the resulting map.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;filter&#39;</span><span class="p">]:</span>
<span class="n">boundsFilter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">rec</span><span class="p">:</span> <span class="n">filter_record</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s">&#39;filter&#39;</span><span class="p">],</span> <span class="n">rec</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">boundsFilter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">a</span><span class="p">:</span> <span class="bp">True</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-41'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-41'>#</a>
</div>
<p>Combine both filters to a single function.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nb">filter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">rec</span><span class="p">:</span> <span class="n">layerFilter</span><span class="p">(</span><span class="n">rec</span><span class="p">)</span> <span class="ow">and</span> <span class="n">boundsFilter</span><span class="p">(</span><span class="n">rec</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-42'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-42'>#</a>
</div>
<p>Load the features from the layer source (e.g. a shapefile).</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">features</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">get_features</span><span class="p">(</span>
<span class="nb">filter</span><span class="o">=</span><span class="nb">filter</span><span class="p">,</span>
<span class="n">min_area</span><span class="o">=</span><span class="n">data</span><span class="p">[</span><span class="s">&quot;min-area&quot;</span><span class="p">],</span>
<span class="n">charset</span><span class="o">=</span><span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;charset&#39;</span><span class="p">]</span>
<span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-43'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-43'>#</a>
</div>
<p>Omit tiny islands, if needed.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;filter-islands&#39;</span><span class="p">]:</span>
<span class="n">features</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">features</span>
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">geometry</span><span class="o">.</span><span class="n">area</span> <span class="o">&gt;</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;filter-islands&#39;</span><span class="p">]]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-44'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-44'>#</a>
</div>
<p>Store computed boundary in cache.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_bounding_geometry_cache</span> <span class="o">=</span> <span class="n">features</span>
<span class="k">return</span> <span class="n">features</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-45'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-45'>#</a>
</div>
<p>returns the output view</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_get_view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-46'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-46'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">format</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;kml&#39;</span><span class="p">,</span> <span class="s">&#39;json&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="n">View</span><span class="p">()</span> <span class="c"># no view transformation needed for KML</span>
<span class="bp">self</span><span class="o">.</span><span class="n">src_bbox</span> <span class="o">=</span> <span class="n">bbox</span> <span class="o">=</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">bounds_poly</span><span class="p">)</span>
<span class="n">opts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span>
<span class="n">exp</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="s">&quot;export&quot;</span><span class="p">]</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">exp</span><span class="p">[</span><span class="s">&quot;width&quot;</span><span class="p">]</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">exp</span><span class="p">[</span><span class="s">&quot;height&quot;</span><span class="p">]</span>
<span class="n">ratio</span> <span class="o">=</span> <span class="n">exp</span><span class="p">[</span><span class="s">&quot;ratio&quot;</span><span class="p">]</span>
<span class="k">if</span> <span class="n">ratio</span> <span class="o">==</span> <span class="s">&quot;auto&quot;</span><span class="p">:</span>
<span class="n">ratio</span> <span class="o">=</span> <span class="n">bbox</span><span class="o">.</span><span class="n">width</span> <span class="o">/</span> <span class="nb">float</span><span class="p">(</span><span class="n">bbox</span><span class="o">.</span><span class="n">height</span><span class="p">)</span>
<span class="k">if</span> <span class="n">h</span> <span class="o">==</span> <span class="s">&quot;auto&quot;</span><span class="p">:</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">w</span> <span class="o">/</span> <span class="n">ratio</span>
<span class="k">elif</span> <span class="n">w</span> <span class="o">==</span> <span class="s">&quot;auto&quot;</span><span class="p">:</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">h</span> <span class="o">*</span> <span class="n">ratio</span>
<span class="k">return</span> <span class="n">View</span><span class="p">(</span><span class="n">bbox</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-47'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-47'>#</a>
</div>
<p>creates a polygon that represents the rectangular view bounds
used for cropping the geometries to not overlap the view</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_init_view_poly</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-48'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-48'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">format</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;kml&#39;</span><span class="p">,</span> <span class="s">&#39;json&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">None</span> <span class="c"># no view polygon needed for KML</span>
<span class="n">w</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">width</span>
<span class="n">h</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">height</span>
<span class="k">return</span> <span class="n">Polygon</span><span class="p">([(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">h</span><span class="p">),</span> <span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="mi">0</span><span class="p">)])</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-49'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-49'>#</a>
</div>
<p>performs polygon simplification</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_simplify_layers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-50'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-50'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="kn">from</span> <span class="nn">simplify</span> <span class="kn">import</span> <span class="n">create_point_store</span><span class="p">,</span> <span class="n">simplify_lines</span>
<span class="n">point_store</span> <span class="o">=</span> <span class="n">create_point_store</span><span class="p">()</span> <span class="c"># create a new empty point store</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-51'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-51'>#</a>
</div>
<p>compute topology for all layers</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;simplify&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="k">for</span> <span class="n">feature</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">feature</span><span class="o">.</span><span class="n">compute_topology</span><span class="p">(</span><span class="n">point_store</span><span class="p">,</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;unify-precision&#39;</span><span class="p">])</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-52'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-52'>#</a>
</div>
<p>break features into lines</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;simplify&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="k">for</span> <span class="n">feature</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">feature</span><span class="o">.</span><span class="n">break_into_lines</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-53'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-53'>#</a>
</div>
<p>simplify lines</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">kept</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;simplify&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="k">for</span> <span class="n">feature</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">feature</span><span class="o">.</span><span class="n">break_into_lines</span><span class="p">()</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">simplify_lines</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;simplify&#39;</span><span class="p">][</span><span class="s">&#39;method&#39;</span><span class="p">],</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;simplify&#39;</span><span class="p">][</span><span class="s">&#39;tolerance&#39;</span><span class="p">])</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span>
<span class="n">total</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">for</span> <span class="n">pt</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">pt</span><span class="o">.</span><span class="n">deleted</span><span class="p">:</span>
<span class="n">kept</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">feature</span><span class="o">.</span><span class="n">restore_geometry</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;filter-islands&#39;</span><span class="p">])</span>
<span class="k">return</span> <span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">kept</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-54'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-54'>#</a>
</div>
<p>cuts the layer features to the map view</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_crop_layers_to_view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-55'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-55'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-56'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-56'>#</a>
</div>
<p>out = []</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">feat</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">feat</span><span class="o">.</span><span class="n">geometry</span><span class="o">.</span><span class="n">is_valid</span><span class="p">:</span>
<span class="k">pass</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-57'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-57'>#</a>
</div>
<p>print feat.geometry
_plot_geometry(feat.geometry)</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">feat</span><span class="o">.</span><span class="n">crop_to</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">view_poly</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-58'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-58'>#</a>
</div>
<p>if not feat.is_empty():
out.append(feat)
layer.features = out</p>
</div>
<div class='code'>
<div class="highlight"><pre></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-59'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-59'>#</a>
</div>
<p>handles crop-to</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_crop_layers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-60'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-60'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;crop-to&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">cropped_features</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">tocrop</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">cbbox</span> <span class="o">=</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">tocrop</span><span class="o">.</span><span class="n">geom</span><span class="p">)</span>
<span class="n">crop_at_layer</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;crop-to&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="n">crop_at_layer</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">KartographError</span><span class="p">(</span><span class="s">&#39;you want to substract &#39;</span>
<span class="o">+</span> <span class="s">&#39;from layer &quot;</span><span class="si">%s</span><span class="s">&quot; which cannot be found&#39;</span>
<span class="o">%</span> <span class="n">crop_at_layer</span><span class="p">)</span>
<span class="k">for</span> <span class="n">crop_at</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layersById</span><span class="p">[</span><span class="n">crop_at_layer</span><span class="p">]</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="k">if</span> <span class="n">crop_at</span><span class="o">.</span><span class="n">geom</span><span class="o">.</span><span class="n">bbox</span><span class="p">()</span><span class="o">.</span><span class="n">intersects</span><span class="p">(</span><span class="n">cbbox</span><span class="p">):</span>
<span class="n">tocrop</span><span class="o">.</span><span class="n">crop_to</span><span class="p">(</span><span class="n">crop_at</span><span class="o">.</span><span class="n">geom</span><span class="p">)</span>
<span class="n">cropped_features</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">tocrop</span><span class="p">)</span>
<span class="n">layer</span><span class="o">.</span><span class="n">features</span> <span class="o">=</span> <span class="n">cropped_features</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-61'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-61'>#</a>
</div>
<h3>Subtract geometry</h3>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_subtract_layers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-62'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-62'>#</a>
</div>
<p>Substract geometry of a layer from the geometry
of one or more different layers. Added mainly
for excluding great lakes from country polygons.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;subtract-from&#39;</span><span class="p">]:</span>
<span class="k">for</span> <span class="n">feat</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="k">if</span> <span class="n">feat</span><span class="o">.</span><span class="n">geom</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">cbbox</span> <span class="o">=</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">feat</span><span class="o">.</span><span class="n">geom</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-63'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-63'>#</a>
</div>
<p>We remove it from multiple layers, if wanted.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">subid</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;subtract-from&#39;</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">subid</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layersById</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">KartographError</span><span class="p">(</span><span class="s">&#39;you want to subtract&#39;</span>
<span class="o">+</span> <span class="s">&#39; from layer &quot;</span><span class="si">%s</span><span class="s">&quot; which cannot be found&#39;</span>
<span class="o">%</span> <span class="n">subid</span><span class="p">)</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layersById</span><span class="p">[</span><span class="n">subid</span><span class="p">]</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">geom</span> <span class="ow">and</span> <span class="n">geom_to_bbox</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">geom</span><span class="p">)</span><span class="o">.</span><span class="n">intersects</span><span class="p">(</span><span class="n">cbbox</span><span class="p">):</span>
<span class="n">s</span><span class="o">.</span><span class="n">subtract_geom</span><span class="p">(</span><span class="n">feat</span><span class="o">.</span><span class="n">geom</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-64'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-64'>#</a>
</div>
<p>Finally, we don't want the subtracted features
to be included in our map.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">layer</span><span class="o">.</span><span class="n">features</span> <span class="o">=</span> <span class="p">[]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-65'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-65'>#</a>
</div>
<h3>Joins features within a layer.</h3>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">_join_features</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-66'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-66'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="kn">from</span> <span class="nn">geometry.utils</span> <span class="kn">import</span> <span class="n">join_features</span>
<span class="k">for</span> <span class="n">layer</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">layers</span><span class="p">:</span>
<span class="k">if</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;join&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">unjoined</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">join</span> <span class="o">=</span> <span class="n">layer</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;join&#39;</span><span class="p">]</span>
<span class="n">groupBy</span> <span class="o">=</span> <span class="n">join</span><span class="p">[</span><span class="s">&#39;group-by&#39;</span><span class="p">]</span>
<span class="n">groups</span> <span class="o">=</span> <span class="n">join</span><span class="p">[</span><span class="s">&#39;groups&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">groups</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-67'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-67'>#</a>
</div>
<p>auto populate groups</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">groups</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">feat</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">fid</span> <span class="o">=</span> <span class="n">feat</span><span class="o">.</span><span class="n">props</span><span class="p">[</span><span class="n">groupBy</span><span class="p">]</span>
<span class="n">groups</span><span class="p">[</span><span class="n">fid</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">fid</span><span class="p">]</span>
<span class="n">groupAs</span> <span class="o">=</span> <span class="n">join</span><span class="p">[</span><span class="s">&#39;group-as&#39;</span><span class="p">]</span>
<span class="n">groupFeatures</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">feat</span> <span class="ow">in</span> <span class="n">layer</span><span class="o">.</span><span class="n">features</span><span class="p">:</span>
<span class="n">found_in_group</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">for</span> <span class="n">g_id</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">:</span>
<span class="k">if</span> <span class="n">g_id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">groupFeatures</span><span class="p">:</span>
<span class="n">groupFeatures</span><span class="p">[</span><span class="n">g_id</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">feat</span><span class="o">.</span><span class="n">props</span><span class="p">[</span><span class="n">groupBy</span><span class="p">]</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">[</span><span class="n">g_id</span><span class="p">]</span> <span class="ow">or</span> <span class="nb">str</span><span class="p">(</span><span class="n">feat</span><span class="o">.</span><span class="n">props</span><span class="p">[</span><span class="n">groupBy</span><span class="p">])</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">[</span><span class="n">g_id</span><span class="p">]:</span>
<span class="n">groupFeatures</span><span class="p">[</span><span class="n">g_id</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">feat</span><span class="p">)</span>
<span class="n">found_in_group</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">break</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">found_in_group</span><span class="p">:</span>
<span class="n">unjoined</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">feat</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-68'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-68'>#</a>
</div>
<p>print unjoined,'features were not joined'</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">for</span> <span class="n">g_id</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">:</span>
<span class="n">props</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">feat</span> <span class="ow">in</span> <span class="n">groupFeatures</span><span class="p">[</span><span class="n">g_id</span><span class="p">]:</span>
<span class="n">fprops</span> <span class="o">=</span> <span class="n">feat</span><span class="o">.</span><span class="n">props</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">fprops</span><span class="p">:</span>
<span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">props</span><span class="p">:</span>
<span class="n">props</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">fprops</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="n">props</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">!=</span> <span class="n">fprops</span><span class="p">[</span><span class="n">key</span><span class="p">]:</span>
<span class="n">props</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;---&quot;</span>
<span class="k">if</span> <span class="n">groupAs</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">props</span><span class="p">[</span><span class="n">groupAs</span><span class="p">]</span> <span class="o">=</span> <span class="n">g_id</span>
<span class="k">if</span> <span class="n">g_id</span> <span class="ow">in</span> <span class="n">groupFeatures</span><span class="p">:</span>
<span class="n">res</span> <span class="o">+=</span> <span class="n">join_features</span><span class="p">(</span><span class="n">groupFeatures</span><span class="p">[</span><span class="n">g_id</span><span class="p">],</span> <span class="n">props</span><span class="p">)</span>
<span class="n">layer</span><span class="o">.</span><span class="n">features</span> <span class="o">=</span> <span class="n">res</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
</div>
</body>