coverage.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 """
00004 This module contains code to plan coverage paths
00005 """
00006 
00007 from shapely.geometry import Point, Polygon, LineString
00008 from shapely.geometry import MultiLineString, MultiPoint
00009 from shapely.geometry import GeometryCollection
00010 from shapely.geos import TopologicalError
00011 import math
00012 import numpy as np
00013 from copy import deepcopy
00014 
00015 from pprint import pprint
00016 
00017 from logging import error
00018 
00019 def generate_intersections(poly, width):
00020     "Subdivide a filed into coverage lines."
00021     starting_breakdown = poly.bounds[0:2]
00022     line = LineString([starting_breakdown, (starting_breakdown[0],
00023                                             starting_breakdown[1] +
00024                                             poly.bounds[3] - poly.bounds[1])])
00025     try:
00026         bounded_line = poly.intersection(line)
00027     except TopologicalError as e:
00028         error("Problem looking for intersection.", exc_info=1)
00029         return
00030     lines = [bounded_line]
00031     iterations = int(math.ceil((poly.bounds[2] - poly.bounds[0]) / width)) + 1
00032     for x in range(1, iterations):
00033         bounded_line = line.parallel_offset(x * width, 'right')
00034         if poly.intersects(bounded_line):
00035             try:
00036                 bounded_line = poly.intersection(bounded_line)
00037             except TopologicalError as e:
00038                 error("Problem looking for intersection.", exc_info=1)
00039                 continue
00040             lines.append(bounded_line)
00041     return lines
00042 
00043 def sort_to(point, list):
00044     "Sorts a set of points by distance to a point"
00045     l = deepcopy(list)
00046     l.sort(lambda x, y: cmp(x.distance(Point(*point)),
00047                             y.distance(Point(*point))))
00048     return l
00049 
00050 def get_furthest(ps, origin):
00051     "Get a point along a line furthest away from a given point"
00052     orig_point = Point(*origin)
00053     return sorted(ps, lambda x, y: cmp(orig_point.distance(Point(*x)),
00054                                        orig_point.distance(Point(*y))))
00055 
00056 def order_points(lines, initial_origin):
00057     "Return a list of points in a given coverage path order"
00058     origin = initial_origin
00059     results = []
00060     while True:
00061         if not len(lines):
00062             break
00063         lines = sort_to(origin, lines)
00064         f = lines.pop(0)
00065         if type(f) == GeometryCollection:
00066             continue
00067         if type(f) == MultiLineString:
00068             for ln in f:
00069                 lines.append(ln)
00070             continue
00071         if type(f) == Point or type(f) == MultiPoint:
00072             continue
00073         xs, ys = f.xy
00074         ps = zip(xs, ys)
00075         (start, end) = get_furthest(ps, origin)
00076         results.append(origin)
00077         # results.append(start)
00078         results.append(start)
00079         # results.append(end)
00080         origin = end
00081     return results
00082 
00083 def bottom_left(points):
00084     """returns the bottom left point from the list of points given"""
00085     pass
00086 
00087 def decompose(polygon, origin=None, width=1.0):
00088     """
00089     Decompose the field into a list of points to cover the field.
00090     """
00091     p = generate_intersections(polygon, width)
00092     if origin == None:
00093         return order_points(p, polygon.bounds[0:2])
00094     else:
00095         return order_points(p, origin)
00096 
00097 if __name__ == '__main__':
00098     from maptools import RotationTransform, rotation_tf_from_longest_edge
00099     from maptools import rotate_polygon_to, make_axis, plot_polygon
00100     from maptools import zoom_extents, rotate_from, plot_line, rotate_to
00101     
00102     ext = [(1, 1), (-3, 11), (4, 16), (10, 10)]
00103     polygon = Polygon(ext)
00104     polygon_points = np.array(polygon.exterior)
00105     
00106     rt = RotationTransform(66)
00107     
00108     tf_polygon = rotate_polygon_to(polygon, rt)
00109     
00110     origin = rotate_to(np.array([(1,1)]),rt).tolist()
00111     
00112     from time import time; start = time()
00113     result = decompose(tf_polygon, origin, width=0.5)
00114     print "Decomposition Time:", time()-start
00115     
00116     tf_result = rotate_from(np.array(result), rt)
00117     
00118     ll = LineString(tf_result)
00119     
00120     ax, _ = make_axis()
00121     plot_polygon(polygon, ax, color='blue')
00122     plot_polygon(tf_polygon, ax, color='blue')
00123     plot_line(ll, ax)
00124     ax.axvline(x=0, color='black')
00125     ax.axhline(y=0, color='black')
00126     zoom_extents(ax, [polygon,tf_polygon])
00127     import pylab; pylab.show()


heatmap
Author(s): Adrian Bauer
autogenerated on Thu Feb 11 2016 23:05:25