示例#1
0
	def process_boundaries(self, new_vertices, boundary_points, lower_bound_x, lower_bound_y, upper_bound_x, upper_bound_y):
		#First task is to remove duplicate points in new vertices
		#Start with first point in list
		#Then loop, if this point is identical to the one before it, dont add
		no_dups = gen_utils.remove_ordered_duplicates(new_vertices)
			
		#Now do second round of processing to insert boundary points
		#Need to find Exit->enter pairs
		#Re shape boudnary list for easier processing
		#If first element is enter, push to back 
		#want Exit then Enter in list
		if boundary_points[0][0] == ENTER:
			boundary_points = boundary_points[1:] + [boundary_points[0]]
			
		#Loop to process exit,enter pairs
		for i in range(0,len(boundary_points)-1):
			#Only look at element i if i is exit, i+1 is enter
			if boundary_points[i][0] == EXIT and boundary_points[i+1][0] == ENTER:
				#Look up points to insert, i
				#Insert them after the exit point int the vertices list
				exit_point = boundary_points[i][1]
				enter_point = boundary_points[i+1][1]
				points_to_insert = exit_enter_window_points_lookup(exit_point,enter_point, lower_bound_x, lower_bound_y, upper_bound_x, upper_bound_y)
				#Now loop through list of vertices and insert after exit
				for i in range(0,len(no_dups)):
					if no_dups[i] == exit_point:
						#Insert points after index i
						no_dups = no_dups[:i+1] + points_to_insert + no_dups[i+1:]
						#End now
						break
			else:
				#Go to next i, currently looking at backwards Enter,Exit pair
				continue
				
		return no_dups
示例#2
0
	def get_fill_points(self):
		#Fill points to return
		rv = []
		#First determine scan line ranges
		top_right,bottom_left = self.get_bounding_box_points()
		
		#Scan lines are horizontal, loop over Y range
		for y in range(int(bottom_left.y),int(top_right.y+1)):
			#Fill points just for this scan line
			scan_line_fill_points = []
			
			#Scan line goes from xmin to x max
			scan_line_p1 = Point()
			scan_line_p1.x = bottom_left.x
			scan_line_p1.y = y
			scan_line_p2 = Point()
			scan_line_p2.x = top_right.x
			scan_line_p2.y = y
			scan_line = Line()
			#The whole line
			scan_line.p1 = scan_line_p1
			scan_line.p2 = scan_line_p2
			
			#For this scan line collect intsection points
			intersection_points = []
			#of all lines from poly
			poly_lines = self.to_lines()
			for poly_line in poly_lines:
				intersection = poly_line.get_intersection_point(scan_line)
				if not(intersection is None):
					#Add intersection point to list
					intersection_points = intersection_points + [intersection]
					
			#Sort the interesection points by x values (for scanning left to right)
			intersection_points.sort(key = lambda p: p.x) #Pythonic indeed
			
			#Remove duplicate intersection points
			intersection_points = gen_utils.remove_ordered_duplicates(intersection_points)
		
			#Process points in groups of 2
			#    p0      p1       p2        p3
			#    enter   exit      enter     exit
			# line p0->p1   and line p2->p3
			i = 0
			p0_is_enter = True
			while i < (len(intersection_points) - 1):
				#Look at two points
				p0 = intersection_points[i]
				p1 = intersection_points[i+1]
				#Get points on this line, dont store yet
				fill_line = Line()
				fill_line.p1 = p0
				fill_line.p2 = p1
				#Get points on this fill line
				scan_line_fill_points = fill_line.render_points()
				
				#If this is an entering point, draw line
				if p0_is_enter:
					rv = rv + scan_line_fill_points
					
				#Now detemine what to do with next point	
				#Determine if next intersection point is entering or exiting
				#If the next intsection point is not a vertex it must be exiting
				if not(p1 in self.vertices):
					#print "p1 NOT in self.vertices"
					#Since p1 is exiting, incrementt i by 2 so next iteration p0 enters
					p0_is_enter = True
					#Inrement i by 2
					i = i + 2
				else:
					#print "p1 in self.vertices"
					#p1 is a vertex
					#Need to decide if it is an entering vertex or exiting
					#Find the index of this vertex in the poly vertex list
					index = -1
					for j in range(0, len(self.vertices)):
						if self.vertices[j] == p1:
							#Found at index i
							index = j
							break
					if index == -1:
						print "Could not find vertex?"
					else:
						#Knowing vertices are in CC order
						#And knowing scan lines are horozontal
						#The vertex to the right of p1 determines if p1 is entering or exiting
						vertex_right_of_p1 = None
						vertex_before_p1 = None #before after in CC order
						vertex_after_p1 = None
						
						#print "len(self.vertices)",len(self.vertices)
						#print "vertex index",index
						
						#Check if this vertex is at beginning or end of list
						#Beginning
						if index == 0:
							#First vertex in list, so 'before' that is last vertex
							vertex_before_p1 = self.vertices[len(self.vertices)-1]
							vertex_after_p1 = self.vertices[1]
						#End of list
						elif index == len(self.vertices) - 1:
							vertex_before_p1 = self.vertices[len(self.vertices)-2]
							vertex_after_p1 = self.vertices[0]
						#Middle of list
						else:
							vertex_before_p1 = self.vertices[index - 1]
							vertex_after_p1 = self.vertices[index + 1]
							
						#Select vertex to right of p1
						if vertex_before_p1.x >= p1.x:
							vertex_right_of_p1 = vertex_before_p1
						elif vertex_after_p1.x >= p1.x:
							vertex_right_of_p1 = vertex_after_p1
						else:
							#No vertex to right? Points saved by now
							#Just exit
							break;
							
						#Need to know if this vertex was before or after and above or below p1
						vertex_right_of_p1_is_above = (vertex_right_of_p1.y >= p1.y)
						vertex_right_of_p1_is_before = (vertex_right_of_p1 == vertex_before_p1)
						
						if vertex_right_of_p1_is_above and vertex_right_of_p1_is_before:
							#Above and before, entering
							#Increment i by 1, next p0 is entering
							p0_is_enter = True
							i = i+1
						elif vertex_right_of_p1_is_above and not(vertex_right_of_p1_is_before):
							#Above and after, exiting
							#Since p1 is exiting, increment i by 2 so next iteration p0 enters
							p0_is_enter = True
							#Inrement i by 2
							i = i + 2
						elif not(vertex_right_of_p1_is_above) and vertex_right_of_p1_is_before:
							#Below and before, exiting
							#Since p1 is exiting, increment i by 2 so next iteration p0 enters
							p0_is_enter = True
							#Inrement i by 2
							i = i + 2
						elif not(vertex_right_of_p1_is_above) and not(vertex_right_of_p1_is_before):
							#Below and and after, entering
							#Increment i by 1, next p0 is entering
							p0_is_enter = True
							i = i+1
						else:
							print "Whoops! Issue with vertex above and below section?"
							
		#Return the fill points
		return rv	
示例#3
0
	def clip_to_window(self,lower_bound_x, lower_bound_y,upper_bound_x, upper_bound_y):
		#Sutherland-Hodgman does not account for polygons that 'leave' the window on one bound
		#and return into the window through another bound (ex. leave through top, enter through bottom)
		#Keep track of points of enter and exit
		#Then use those points to look up 
		#which points need to be inserted to complete polygon
		#Will be list of tuples ([ENTER|EXIT],<Point>)
		boundary_points = []
		
		#Make new list of vertices for this clipped polygon
		new_vertices = []
		#Loop over vertices
		#Easiest to loop through if has duplicate end vertex
		wduplicate = self.vertices + [self.vertices[0]]	
		for i in range(0,len(wduplicate)-1):
			current_v = wduplicate[i]
			next_v = wduplicate[i+1]
			#Make line using these
			line = Line()
			#Do not reference points, copy
			line.p1 = copy.deepcopy(current_v)
			line.p2 = copy.deepcopy(next_v)
			
			#Make copy that will not be modified
			orig_line = copy.deepcopy(line)
			
			#print "Clipping line p1->p2:"
			#print orig_line
						
			#Clip this line
			clipped_line = line.clip_to_window(lower_bound_x, lower_bound_y,upper_bound_x, upper_bound_y)
			if clipped_line is None:
				#No part of line this is in window
				#Do not add either vertex to new polygon
				#print "Line not in window"
				#print
				continue
			elif clipped_line == orig_line:
				#Line did not change
				#print "Line unchanged"
				#print orig_line,"=",clipped_line
				#print
				#Save these vertices
				new_vertices = new_vertices + [clipped_line.p1,clipped_line.p2]
			else:
				#Line was clipped		
				#print "Line clipped p1->p2:"
				#print clipped_line
				#Need to figure out if p1,p2 or both were clipped
				p1_clipped = not(clipped_line.p1 == orig_line.p1)
				p2_clipped = not(clipped_line.p2 == orig_line.p2)
				#print "P1 Clipped?:",p1_clipped
				#print "P2 Clipped?:",p2_clipped
				#Knowing points are in cc order
				#print
				#p1 clipped only means p1 entering
				#p2 clipped only means p2 exiting
				if p1_clipped:
					#Just p1 clipped
					enter_point = copy.deepcopy(clipped_line.p1)
					boundary_points = boundary_points + [(ENTER,enter_point)]
				if p2_clipped:
					#Just p2 clipped
					exit_point = copy.deepcopy(clipped_line.p2)
					boundary_points = boundary_points + [(EXIT,exit_point)]
				
				#Still save both points of clipped line
				new_vertices = new_vertices + [clipped_line.p1,clipped_line.p2]
				
		
		#Do we have boundary points to process?
		rv = None
		if len(boundary_points) <= 0:
			#No, return now
			self.vertices = new_vertices
			rv = self
		else:
			#Do boundary processing and return vertices
			verts = self.process_boundaries(new_vertices, boundary_points, lower_bound_x, lower_bound_y, upper_bound_x, upper_bound_y)
			self.vertices = verts
			rv = self
			
		#Remove duplicate vertices
		self.vertices = gen_utils.remove_ordered_duplicates(self.vertices)
			
		#Before returning, final check of if the whole polygon was clipped away
		if len(self.vertices) <= 0:
			return None
		elif len(self.vertices) <= 2:
			#Clipped down to a line?
			#print "Polygon clipped to line?"
			return None
		else:
			return rv