Skip to content

Commit

Permalink
Partial python3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
sseemayer committed Jul 1, 2013
1 parent 7de0eb3 commit b1f434d
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 78 deletions.
2 changes: 1 addition & 1 deletion examples/__init__.py
Expand Up @@ -106,7 +106,7 @@ def example_from_string(self, example_name):


package_name, class_name = example_name.rsplit('.', 1)
package = __import__(package_name, globals(), locals(), [class_name], -1)
package = __import__(package_name, globals(), locals(), [class_name], 1)

cls = next((c[1] for c in inspect.getmembers(package, inspect.isclass) if c[0] == class_name))

Expand Down
66 changes: 33 additions & 33 deletions py2d/FOV.py
@@ -1,19 +1,19 @@
"""Calculation of polygonal Field of View (FOV)"""

import Math
import functools
import py2d.Math

class Vision:
"""Class for representing a polygonal field of vision (FOV).
It requires a list of obstructors, given as line strips made of lists of vectors (i.e. we have a list of lists of vectors).
The vision polygon will be cached as long as the eye position and obstructors don't change.
The vision polygon will be cached as long as the eye position and obstructors don't change.
>>> obs = [[ Math.Vector(2,4), Math.Vector(4, 1), Math.Vector(7, -2) ],
... [ Math.Vector(1,-2), Math.Vector(6, -3) ],
... [ Math.Vector(2.5,5), Math.Vector(3, 4) ]]
>>> obs = [[ py2d.Math.Vector(2,4), py2d.Math.Vector(4, 1), py2d.Math.Vector(7, -2) ],
... [ py2d.py2d.Math.Vector(1,-2), py2d.Math.Vector(6, -3) ],
... [ py2d.Math.Vector(2.5,5), py2d.Math.Vector(3, 4) ]]
>>> radius = 20
>>> eye = Math.Vector(0,0)
>>> boundary = Math.Polygon.regular(eye, radius, 4)
>>> eye = py2d.Math.Vector(0,0)
>>> boundary = py2d.Math.Polygon.regular(eye, radius, 4)
>>> v = Vision(obs)
>>> poly = v.get_vision(eye, radius, boundary)
>>> poly.points[0:6]
Expand All @@ -36,28 +36,28 @@ def __init__(self, obstructors, debug=False):

def set_obstructors(self, obstructors):
"""Set new obstructor data for the Vision object.
This will also cause the vision polygon to become invalidated, resulting in a re-calculation the next time you access it.
@type obstructors: list
@param obstructors: A list of obstructors. Obstructors are a list of vectors, so this should be a list of lists.
"""
def flatten_list(l):
return reduce(lambda x,y: x+y, l)
return functools.reduce(lambda x,y: x+y, l)

# concatenate list of lists of vectors to a list of vectors
self.obs_points = flatten_list(obstructors)
self.obs_points = flatten_list(obstructors)

# convert obstructor line strips to lists of line segments
self.obs_segs = flatten_list([ zip(strip, strip[1:]) for strip in obstructors ])
self.obs_segs = flatten_list([ list(zip(strip, strip[1:])) for strip in obstructors ])

self.cached_vision = None
self.cached_position = None
self.cached_radius = None

def get_vision(self, eye, radius, boundary):
"""Get a vision polygon for a given eye position and boundary Polygon.
@type eye: Vector
@param eye: The position of the viewer (normally the center of the boundary polygon)
@type radius: float
Expand All @@ -75,8 +75,8 @@ def get_vision(self, eye, radius, boundary):
def calculate(self, eye, radius, boundary):
"""Re-calculate the vision polygon.
WARNING: You should only call this if you want to re-calculate the vision polygon for some reason.
WARNING: You should only call this if you want to re-calculate the vision polygon for some reason.
For normal usage, use L{get_vision} instead!
"""

Expand All @@ -87,13 +87,13 @@ def calculate(self, eye, radius, boundary):

radius_squared = radius * radius


closest_points = lambda points, reference: sorted(points, key=lambda p: (p - reference).get_length_squared())


def sub_segment(small, big):
return Math.distance_point_lineseg_squared(small[0], big[0], big[1]) < 0.0001 and Math.distance_point_lineseg_squared(small[1], big[0], big[1]) < 0.0001
return py2d.Math.distance_point_lineseg_squared(small[0], big[0], big[1]) < 0.0001 and py2d.Math.distance_point_lineseg_squared(small[1], big[0], big[1]) < 0.0001


def segment_in_obs(seg):
for line_segment in self.obs_segs:
Expand All @@ -106,44 +106,44 @@ def check_visibility(p):

if p not in bpoints:
if (eye - p).get_length_squared() > radius_squared: return False
if not boundary.contains_point(p): return False
if not boundary.contains_point(p): return False

for line_segment in obs_segs:
if Math.check_intersect_lineseg_lineseg( eye, p, line_segment[0], line_segment[1]):
if py2d.Math.check_intersect_lineseg_lineseg( eye, p, line_segment[0], line_segment[1]):
if line_segment[0] != p and line_segment[1] != p:
return False

return True

def lineseg_in_radius(seg):
return Math.distance_point_lineseg_squared(eye, seg[0], seg[1]) <= radius_squared
return py2d.Math.distance_point_lineseg_squared(eye, seg[0], seg[1]) <= radius_squared

obs_segs = filter(lineseg_in_radius, self.obs_segs)

# add all obstruction points and boundary points directly visible from the eye
visible_points = list(filter(check_visibility, set(self.obs_points + boundary.points )))

# find all obstructors intersecting the vision polygon
boundary_intersection_points = Math.intersect_linesegs_linesegs(obs_segs, zip(boundary.points, boundary.points[1:]) + [(boundary.points[-1], boundary.points[0])])
boundary_intersection_points = py2d.Math.intersect_linesegs_linesegs(obs_segs, list(zip(boundary.points, boundary.points[1:])) + [(boundary.points[-1], boundary.points[0])])

if self.debug: self.debug_points.extend([(p, 0xFF0000) for p in visible_points])
if self.debug: self.debug_points.extend([(p, 0x00FFFF) for p in boundary_intersection_points])

# filter boundary_intersection_points to only include visible points
# filter boundary_intersection_points to only include visible points
# - need extra code here to handle points on obstructors!
for line_segment in obs_segs:
for line_segment in obs_segs:
i = 0
while i < len(boundary_intersection_points):
p = boundary_intersection_points[i]
if Math.distance_point_lineseg_squared(p, line_segment[0], line_segment[1]) > 0.0001 and Math.check_intersect_lineseg_lineseg(eye, p, line_segment[0], line_segment[1]):

if py2d.Math.distance_point_lineseg_squared(p, line_segment[0], line_segment[1]) > 0.0001 and py2d.Math.check_intersect_lineseg_lineseg(eye, p, line_segment[0], line_segment[1]):
boundary_intersection_points.remove(p)
else:
i+=1

visible_points += boundary_intersection_points

poly = Math.Polygon()
poly = py2d.Math.Polygon()
poly.add_points(visible_points)
poly.sort_around(eye)

Expand All @@ -154,7 +154,7 @@ def lineseg_in_radius(seg):
n = poly.points[ (i+1) % len(poly.points) ]

# intersect visible point with obstructors and boundary polygon
intersections = set(Math.intersect_linesegs_ray(obs_segs, eye, c) + Math.intersect_poly_ray(boundary.points, eye, c))
intersections = set(py2d.Math.intersect_linesegs_ray(obs_segs, eye, c) + py2d.Math.intersect_poly_ray(boundary.points, eye, c))

intersections = [ip for ip in intersections if ip != c and boundary.contains_point(ip)]

Expand Down Expand Up @@ -185,7 +185,7 @@ def lineseg_in_radius(seg):
i-=1

elif sio_pc and not sio_cn:

#if self.debug: print "insert %s at %d (+)" % (closest_intersection, i+1)
poly.points.insert(i+1, intersection)
i+=1
Expand Down
6 changes: 3 additions & 3 deletions py2d/Math/Operations.py
Expand Up @@ -29,7 +29,7 @@ def intersect_poly_lineseg(poly_points, p1, p2):
@return: The list of intersection points or an empty list
"""
return intersect_linesegs_lineseg(zip(poly_points[0:], poly_points[1:]) + [(poly_points[-1], poly_points[0])], p1, p2)
return intersect_linesegs_lineseg(list(zip(poly_points[0:], poly_points[1:])) + [(poly_points[-1], poly_points[0])], p1, p2)

def intersect_poly_ray(poly_points, p1, p2):
"""Intersect a polygon and a ray
Expand All @@ -45,7 +45,7 @@ def intersect_poly_ray(poly_points, p1, p2):
@return: The list of intersection points or an empty list
"""
return intersect_linesegs_ray(zip(poly_points[0:], poly_points[1:]) + [(poly_points[-1], poly_points[0])], p1, p2)
return intersect_linesegs_ray(list(zip(poly_points[0:], poly_points[1:])) + [(poly_points[-1], poly_points[0])], p1, p2)

def intersect_line_line(p1, p2, q1, q2):
"""Intersect two lines
Expand Down Expand Up @@ -181,7 +181,7 @@ def intersect_poly_poly(poly_points1, poly_points2):
@return: The list of intersections or an empty list
"""

return intersect_linesegs_linesegs(zip(poly_points1[0:], poly_points1[1:]) + [(poly_points1[-1], poly_points1[0])], zip(poly_points2[0:], poly_points2[1:]) + [(poly_points2[-1], poly_points2[0])])
return intersect_linesegs_linesegs(list(zip(poly_points1[0:], poly_points1[1:])) + [(poly_points1[-1], poly_points1[0])], list(zip(poly_points2[0:], poly_points2[1:])) + [(poly_points2[-1], poly_points2[0])])

def intersect_linesegs_linesegs(segs1, segs2):
"""Intersect two lists of line segments
Expand Down
27 changes: 14 additions & 13 deletions py2d/Math/Polygon.py
@@ -1,4 +1,5 @@
import math
import itertools
from collections import defaultdict

from py2d.Math.Vector import *
Expand Down Expand Up @@ -201,8 +202,8 @@ def inorder_extend(v, v1, v2, ints):
# find all intersections
intersections_a = defaultdict(list)
intersections_b = defaultdict(list)
for a1, a2 in zip(v_a, v_a[1:]) + [(v_a[-1], v_a[0])]:
for b1, b2 in zip(v_b, v_b[1:]) + [(v_b[-1], v_b[0])]:
for a1, a2 in list(zip(v_a, v_a[1:])) + [(v_a[-1], v_a[0])]:
for b1, b2 in list(zip(v_b, v_b[1:])) + [(v_b[-1], v_b[0])]:
i = intersect_lineseg_lineseg(a1[0],a2[0],b1[0],b2[0])
if i:
intersections_a[(a1[0],a2[0])].append(i)
Expand All @@ -220,7 +221,7 @@ def inorder_extend(v, v1, v2, ints):
edge_fragments = defaultdict(list)

def extend_fragments(v, poly, fragment_type):
for v1, v2 in zip(v, v[1:]) + [(v[-1], v[0])]:
for v1, v2 in list(zip(v, v[1:])) + [(v[-1], v[0])]:
if v1[1] == fragment_type or v2[1] == fragment_type:
# one of the vertices is of the required type
edge_fragments[v1[0]].append( v2[0] )
Expand All @@ -241,7 +242,7 @@ def extend_fragments(v, poly, fragment_type):
def print_edge():
for k in edge_fragments.keys():
for v in edge_fragments[k]:
print "%s -> %s" % (k, v)
print("%s -> %s" % (k, v))



Expand All @@ -261,7 +262,7 @@ def print_edge():
# get only the cyclic part of the sequence
sequence = sequence[sequence.index(current):]

for c,n in zip(sequence, sequence[1:]) + [(sequence[-1], sequence[0])]:
for c,n in list(zip(sequence, sequence[1:])) + [(sequence[-1], sequence[0])]:
edge_fragments[c].remove(n)

if not edge_fragments[c]:
Expand Down Expand Up @@ -459,7 +460,7 @@ def winding_number(p, raw):

wn = 0
for pp in raw:
for a,b in zip(pp, pp[1:]) + [(pp[-1], pp[0])]:
for a,b in list(zip(pp, pp[1:])) + [(pp[-1], pp[0])]:
if a.y < p.y and b.y > p.y:
i = intersect_lineseg_ray(a,b,p,p+VECTOR_X)
if i and i.x > p.x:
Expand Down Expand Up @@ -615,7 +616,7 @@ def handle_holes(l, d_a, d_b):
while intersecting:
intersecting = False
for hole in holes:
for a,b in zip(hole, hole[1:]) + [(hole[-1],hole[0])]:
for a,b in list(zip(hole, hole[1:])) + [(hole[-1],hole[0])]:
i = intersect_lineseg_lineseg(d_a, d_b, a, b)
if i and i not in [a,b]:
if not closest_intersection or (closest_intersection - d_b).length_squared > (i-d_b).length_squared:
Expand Down Expand Up @@ -679,10 +680,10 @@ def try_decompose(i_start):


# find the next notch index
i_extend = next( ( i for i in range(i_start+1, len(p)) + range(0,i_start+1) if not point_orientation( p[i-1], p[i], p[(i+1) % len(p)] ) ) )
i_extend = next( ( i for i in itertools.chain(range(i_start+1, len(p)), range(0,i_start+1)) if not point_orientation( p[i-1], p[i], p[(i+1) % len(p)] ) ) )

# build provisional l
l = range(i_start,i_extend+1) if i_start < i_extend else range(i_start,len(p)) + range(0,i_extend+1)
l = list(range(i_start,i_extend+1)) if i_start < i_extend else list(range(i_start,len(p))) + list(range(0,i_extend+1))

#print "l=%s" % l

Expand All @@ -695,9 +696,9 @@ def try_decompose(i_start):
#print "l'=%s" % l

# try to extend l counter-clockwise - find next notch
i_extend2 = next( ( i for i in range(i_start,-1,-1) + range(len(p)-1,i_start, -1) if not point_orientation( p[i-1], p[i], p[(i+1) % len(p)] ) ) )
i_extend2 = next( ( i for i in itertools.chain((i_start,-1,-1), range(len(p)-1,i_start, -1)) if not point_orientation( p[i-1], p[i], p[(i+1) % len(p)] ) ) )

l2 = range(i_extend2,len(p)) + range(0,i_start) if i_extend2 > i_start else range(i_extend2,i_start)
l2 = list(range(i_extend2,len(p))) + list(range(0,i_start)) if i_extend2 > i_start else list(range(i_extend2,i_start))

#print "l2=%s" % l2

Expand Down Expand Up @@ -779,7 +780,7 @@ def is_clockwise(self):
@staticmethod
def is_clockwise_s(pts):
# get index of point with minimal x value
i_min = min(xrange(len(pts)), key=lambda i: pts[i].x)
i_min = min(range(len(pts)), key=lambda i: pts[i].x)

# get previous, current and next points
a = pts[i_min-1]
Expand Down Expand Up @@ -825,7 +826,7 @@ def contains_point_s(pts, p) :
"""Checks if the polygon defined by the point list pts contains the point p"""

# see if we find a line segment that p is on
for a,b in zip(pts[0:], pts[1:]) + [(pts[-1], pts[0])]:
for a,b in list(zip(pts[0:], pts[1:])) + [(pts[-1], pts[0])]:
d = distance_point_lineseg_squared(p, a, b)
if d < EPSILON * EPSILON: return 2

Expand Down

0 comments on commit b1f434d

Please sign in to comment.