Ejemplo n.º 1
0
Archivo: FOV.py Proyecto: tartley/Py2D
	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. 
		
		For normal usage, use L{get_vision} instead!
		"""

		self.cached_radius = radius
		self.cached_position = eye
		self.debug_points = []
		self.debug_linesegs = []

		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
				

		def segment_in_obs(seg):
			for line_segment in self.obs_segs:
				if sub_segment(seg, line_segment):
					return True
			return False

		def check_visibility(p):
			bpoints = set(boundary.points)

			if p not in bpoints:
				if (eye - p).get_length_squared() > radius_squared: 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 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

		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])])
		
		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 
		# - need extra code here to handle points on obstructors!
		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]):
					boundary_intersection_points.remove(p)
				else:
					i+=1

		visible_points += boundary_intersection_points

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

		i = 0
		while i < len(poly.points):
			p = poly.points[i-1]
			c = poly.points[i]
			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 = [ip for ip in intersections if ip != c and boundary.contains_point(ip)]


			if self.debug: self.debug_points.extend([(pt, 0x00FF00) for pt in intersections])
			if intersections:

				intersection = min(intersections, key=lambda p: (p - eye).length_squared)

				#if self.debug: self.debug_linesegs.append((0xFF00FF, [eye, intersection]))

				#if self.debug: print "%d prev: %s current: %s next: %s" % (i, p, c, n)

				sio_pc = segment_in_obs((p,c))
				sio_cn = segment_in_obs((c,n))

				if not sio_pc:
					#if self.debug: print "insert %s at %d" % (closest_intersection, i)
					poly.points.insert(i, intersection)
					i+=1


					# We might have wrongly inserted a point before because this insert was missing
					# and therefore the current-next check (incorrectly) yielded false. remove the point again
					if segment_in_obs((poly.points[i-3], poly.points[i-1])):
						#if self.debug: print "Fixing erroneous insert at %d" % (i-2)
						poly.points.remove(poly.points[i-2])
						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

				#elif self.debug:
					#print "no insert at %i" % i


			i+=1

			#if self.debug: print "%d %d" % (i, len(poly.points))


		# handle border case where polypoint at 0 is wrongfully inserted before because poly was not finished at -1
		if segment_in_obs((poly.points[-1], poly.points[1])):
			poly.points[0], poly.points[1] = poly.points[1], poly.points[0]


		self.cached_vision = poly

		return poly
Ejemplo n.º 2
0
Archivo: FOV.py Proyecto: tartley/Py2D
		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
Ejemplo n.º 3
0
Archivo: FOV.py Proyecto: tartley/Py2D
		def lineseg_in_radius(seg):
			return Math.distance_point_lineseg_squared(eye, seg[0], seg[1]) <= radius_squared