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]) | ||||
|         :return: List of Polygon objects | ||||
|         """ | ||||
|         import float_raster | ||||
|         xy_complex = self.vertices[:, 0] + 1j * self.vertices[:, 1] | ||||
|         xy_cleaned = _clean_complex_vertices(xy_complex) | ||||
|         xy = numpy.vstack((numpy.real(xy_cleaned)[None, :], | ||||
|                            numpy.imag(xy_cleaned)[None, :])) | ||||
|         import pyclipper | ||||
|         from pyclipper import scale_to_clipper, scale_from_clipper | ||||
| 
 | ||||
|         if cut_xs is None: | ||||
|             cut_xs = tuple() | ||||
|         if cut_ys is None: | ||||
|             cut_ys = tuple() | ||||
|         min_x, min_y = numpy.min(self.vertices, axis=0) | ||||
|         max_x, max_y = numpy.max(self.vertices, axis=0) | ||||
|         range_x = max_x - min_x | ||||
|         range_y = max_y - min_y | ||||
| 
 | ||||
|         mins, maxs = self.get_bounds() | ||||
|         dx, dy = maxs - mins | ||||
|         edge_xs = (min_x - range_x - 1,) + tuple(cut_xs) + (max_x + range_x + 1,) | ||||
|         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)) | ||||
|         cy = numpy.hstack((min(tuple(cut_ys) + (mins[1],)) - dy, cut_ys, max((maxs[1],) + tuple(cut_ys)) + dy)) | ||||
|         clipped_shapes = [] | ||||
|         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) | ||||
| 
 | ||||
|         polygons = [] | ||||
|         for cx_min, cx_max in zip(cx, cx[1:]): | ||||
|             for cy_min, cy_max in zip(cy, cy[1:]): | ||||
|                 clipped_verts = (numpy.real(all_verts).clip(cx_min, cx_max) + 1j * | ||||
|                                  numpy.imag(all_verts).clip(cy_min, cy_max)) | ||||
| 
 | ||||
|                 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 | ||||
|                 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]): | ||||
|                         clipper.AddPath(scale_to_clipper(( | ||||
|                             (start_x, start_y), | ||||
|                             (start_x, stop_y), | ||||
|                             (stop_x, stop_y), | ||||
|                             (stop_x, start_y), | ||||
|                         )), pyclipper.PT_CLIP, True) | ||||
| 
 | ||||
|                 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 | ||||
|         return self | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user