Advertisement
Marrin

tin_reducer_gml 0.2

Sep 24th, 2013
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import time
  2. from osgeo import ogr
  3. from pywps.Process.Process import WPSProcess
  4.  
  5.  
  6. def iter_points(layer):
  7.     for feature in layer:
  8.         exterior_ring = feature.GetGeometryRef().GetGeometryRef(0)
  9.         for i in xrange(exterior_ring.GetPointCount()):
  10.             yield exterior_ring.GetPoint(i)
  11.  
  12.  
  13. def clean_points(points):
  14.     #
  15.     # Delete the last point of each triangle (we only need three point for our
  16.     # calculations)
  17.     #
  18.     # TODO: The code below has the effect of the original code but it doesn't
  19.     #       match the description above and it repeats points which will get
  20.     #       filtered out in a later processing step anyway.  I guess the
  21.     #       `drop_every_nth()` function below is actually wanted here instead.
  22.     #
  23.     points = iter(points)
  24.     try:
  25.         while True:
  26.             yield next(points)
  27.             next(points)
  28.             point = next(points)
  29.             yield point
  30.             yield point
  31.             next(points)
  32.     except StopIteration:
  33.         pass  # Ignored intentionally.
  34.  
  35.  
  36. def drop_every_nth(nth, iterable):
  37.     return (item for i, item in enumerate(iterable, 1) if i % nth != 0)
  38.  
  39.  
  40. def distance(point_a, point_b):
  41.     #
  42.     # TODO: To be the usual euklidean distance formula it lacks a `math.sqrt()`
  43.     #       call!
  44.     #
  45.     return sum((a - b)**2 for a, b in zip(point_a, point_b))
  46.  
  47.  
  48. def filter_close_points(minimal_distance, points):
  49.     #
  50.     # TODO: The reversing is only neccessary if the points have to be looked
  51.     #       at in the order they are given to this function.  If going through
  52.     #       them in reverse would be okay we could spare this step.
  53.     #
  54.     points = list(reversed(points))
  55.     while points:
  56.         point = points.pop()
  57.         point_count = len(points)
  58.         points = [p for p in points if distance(point, p) >= minimal_distance]
  59.         if len(points) == point_count:
  60.             yield point
  61.  
  62.  
  63. def create_geometry(points):
  64.     geometry = ogr.Geometry(ogr.wkbMultiPoint)
  65.     wkb_point = ogr.Geometry(ogr.wkbPoint)
  66.     for point in points:
  67.         wkb_point.AddPoint(*point)
  68.         geometry.AddGeometry(wkb_point)
  69.     return geometry
  70.  
  71.  
  72. class Process(WPSProcess):
  73.     def __init__(self):
  74.         WPSProcess.__init__(
  75.             self,
  76.             identifier=__name__,
  77.             title='Pollmueller Tin-Reducer',
  78.             version = '0.1',
  79.             storeSupported='true',
  80.             statusSupported='true',
  81.             abstract=(
  82.                 'reduces the points of a given triangulated irregular network'
  83.                 ' by a variable factor'
  84.             ),
  85.             grassLocation=False
  86.         )
  87.         self.data_output = self.addComplexOutput(
  88.             identifier='output',
  89.             title='Output vector data',
  90.             formats=[{'mimeType': 'text/xml'}]
  91.         )
  92.         self.time_output = self.addLiteralOutput(
  93.             identifier='output2',
  94.             title='computation time (to compare different approaches)'
  95.         )
  96.         self.data_filename_input = self.addComplexInput(
  97.             identifier='data',
  98.             title='Input vector data',
  99.             formats=[{'mimeType': 'text/xml'}]
  100.         )
  101.         self.minimal_distance_input = self.addLiteralInput(
  102.             identifier='input2', title='minimal distance between points'
  103.         )
  104.  
  105.     def execute(self):
  106.         #
  107.         # TODO: Different operating systems have different semantics and
  108.         #       resolutions for `time()` and `clock()`.  Make sure `clock()` is
  109.         #       the correct one here.
  110.         #
  111.         start_timestamp = time.clock()
  112.  
  113.         shape_file = ogr.Open(self.data_filename_input.getValue())
  114.         if shape_file is None:
  115.             raise Exception('failed to open shape file.')
  116.         #
  117.         # Get the first layer.
  118.         #
  119.         layer = shape_file.GetLayer(0)
  120.         layer.ResetReading()
  121.         points = filter_close_points(
  122.             self.minimal_distance_input.getValue(),
  123.             clean_points(iter_points(layer))
  124.         )
  125.         gml = create_geometry(points).ExportToGML()
  126.  
  127.         elapsed_time = time.clock() - start_timestamp
  128.         self.data_output.setValue(gml)
  129.         self.time_output.setValue(elapsed_time)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement