use pyclipper for polygon cutting
This commit is contained in:
		
							parent
							
								
									b3f99ee123
								
							
						
					
					
						commit
						87c2ef5948
					
				| @ -185,63 +185,37 @@ class Polygon(Shape): | |||||||
|         :param cut_ys: list of y-coordinates to cut along (e.g., [1, 3, 5.4]) |         :param cut_ys: list of y-coordinates to cut along (e.g., [1, 3, 5.4]) | ||||||
|         :return: List of Polygon objects |         :return: List of Polygon objects | ||||||
|         """ |         """ | ||||||
|         import float_raster |         import pyclipper | ||||||
|         xy_complex = self.vertices[:, 0] + 1j * self.vertices[:, 1] |         from pyclipper import scale_to_clipper, scale_from_clipper | ||||||
|         xy_cleaned = _clean_complex_vertices(xy_complex) |  | ||||||
|         xy = numpy.vstack((numpy.real(xy_cleaned)[None, :], |  | ||||||
|                            numpy.imag(xy_cleaned)[None, :])) |  | ||||||
| 
 | 
 | ||||||
|         if cut_xs is None: |         min_x, min_y = numpy.min(self.vertices, axis=0) | ||||||
|             cut_xs = tuple() |         max_x, max_y = numpy.max(self.vertices, axis=0) | ||||||
|         if cut_ys is None: |         range_x = max_x - min_x | ||||||
|             cut_ys = tuple() |         range_y = max_y - min_y | ||||||
| 
 | 
 | ||||||
|         mins, maxs = self.get_bounds() |         edge_xs = (min_x - range_x - 1,) + tuple(cut_xs) + (max_x + range_x + 1,) | ||||||
|         dx, dy = maxs - mins |         edge_ys = (min_y - range_y - 1,) + tuple(cut_ys) + (max_y + range_y + 1,) | ||||||
| 
 | 
 | ||||||
|         cx = numpy.hstack((min(tuple(cut_xs) + (mins[0],)) - dx, cut_xs, max((maxs[0],) + tuple(cut_xs)) + dx)) |         clipped_shapes = [] | ||||||
|         cy = numpy.hstack((min(tuple(cut_ys) + (mins[1],)) - dy, cut_ys, max((maxs[1],) + tuple(cut_ys)) + dy)) |         for i in range(2): | ||||||
|  |             for j in range(2): | ||||||
|  |                 clipper = pyclipper.Pyclipper() | ||||||
|  |                 clipper.AddPath(scale_to_clipper(self.vertices), pyclipper.PT_SUBJECT, True) | ||||||
| 
 | 
 | ||||||
|         all_verts = float_raster.create_vertices(xy, cx, cy) |                 for start_x, stop_x in zip(edge_xs[i::2], edge_xs[(i+1)::2]): | ||||||
| 
 |                     for start_y, stop_y in zip(edge_ys[j::2], edge_ys[(j+1)::2]): | ||||||
|         polygons = [] |                         clipper.AddPath(scale_to_clipper(( | ||||||
|         for cx_min, cx_max in zip(cx, cx[1:]): |                             (start_x, start_y), | ||||||
|             for cy_min, cy_max in zip(cy, cy[1:]): |                             (start_x, stop_y), | ||||||
|                 clipped_verts = (numpy.real(all_verts).clip(cx_min, cx_max) + 1j * |                             (stop_x, stop_y), | ||||||
|                                  numpy.imag(all_verts).clip(cy_min, cy_max)) |                             (stop_x, start_y), | ||||||
| 
 |                         )), pyclipper.PT_CLIP, True) | ||||||
|                 cleaned_verts = _clean_complex_vertices(clipped_verts) |  | ||||||
|                 if len(cleaned_verts) == 0: |  | ||||||
|                     continue |  | ||||||
| 
 |  | ||||||
|                 final_verts = numpy.hstack((numpy.real(cleaned_verts)[:, None], |  | ||||||
|                                             numpy.imag(cleaned_verts)[:, None])) |  | ||||||
|                 polygons.append(Polygon( |  | ||||||
|                     vertices=final_verts, |  | ||||||
|                     layer=self.layer, |  | ||||||
|                     dose=self.dose)) |  | ||||||
|         return polygons |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def _clean_complex_vertices(vertices: numpy.ndarray) -> numpy.ndarray: |  | ||||||
|     eps = numpy.finfo(vertices.dtype).eps |  | ||||||
| 
 |  | ||||||
|     def cleanup(v): |  | ||||||
|         # Remove duplicate points |  | ||||||
|         dv = v - numpy.roll(v, 1) |  | ||||||
|         v = v[numpy.abs(dv) > eps] |  | ||||||
| 
 |  | ||||||
|         # Remove colinear points |  | ||||||
|         dv = v - numpy.roll(v, 1) |  | ||||||
|         m = numpy.angle(dv) % pi |  | ||||||
|         diff_m = m - numpy.roll(m, -1) |  | ||||||
|         return v[numpy.abs(diff_m) > eps] |  | ||||||
| 
 |  | ||||||
|     n = len(vertices) |  | ||||||
|     cleaned = cleanup(vertices) |  | ||||||
|     while n != len(cleaned): |  | ||||||
|         n = len(cleaned) |  | ||||||
|         cleaned = cleanup(cleaned) |  | ||||||
| 
 |  | ||||||
|     return cleaned |  | ||||||
| 
 | 
 | ||||||
|  |                 clipped_parts = scale_from_clipper(clipper.Execute(pyclipper.CT_INTERSECTION, | ||||||
|  |                                                                    pyclipper.PFT_EVENODD, | ||||||
|  |                                                                    pyclipper.PFT_EVENODD)) | ||||||
|  |                 for part in clipped_parts: | ||||||
|  |                     poly = self.copy() | ||||||
|  |                     poly.vertices = part | ||||||
|  |                     clipped_shapes.append(poly) | ||||||
|  |         return clipped_shapes | ||||||
|  | |||||||
| @ -156,4 +156,3 @@ class SubPattern: | |||||||
|         """ |         """ | ||||||
|         self.scale *= c |         self.scale *= c | ||||||
|         return self |         return self | ||||||
| 
 |  | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								setup.py
									
									
									
									
									
								
							| @ -16,7 +16,8 @@ setup(name='masque', | |||||||
|           'visualization': ['matplotlib'], |           'visualization': ['matplotlib'], | ||||||
|           'gdsii': ['python-gdsii'], |           'gdsii': ['python-gdsii'], | ||||||
|           'svg': ['svgwrite'], |           'svg': ['svgwrite'], | ||||||
|           'text': ['freetype-py', 'matplotlib'] |           'text': ['freetype-py', 'matplotlib'], | ||||||
|  |           'clipping': ['pyclipper'], | ||||||
|       }, |       }, | ||||||
|       ) |       ) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user