snapshot 2019-04-20 13:34:52.427189
This commit is contained in:
		
							parent
							
								
									fa66e09f9b
								
							
						
					
					
						commit
						bab12add10
					
				| @ -15,7 +15,7 @@ import logging | |||||||
| 
 | 
 | ||||||
| from .utils import mangle_name, make_dose_table | from .utils import mangle_name, make_dose_table | ||||||
| from .. import Pattern, SubPattern, GridRepetition, PatternError, Label, Shape | from .. import Pattern, SubPattern, GridRepetition, PatternError, Label, Shape | ||||||
| from ..shapes import Polygon | from ..shapes import Polygon, Path | ||||||
| from ..utils import rotation_matrix_2d, get_bit, set_bit, vector2, is_scalar | from ..utils import rotation_matrix_2d, get_bit, set_bit, vector2, is_scalar | ||||||
| from ..utils import remove_colinear_vertices | from ..utils import remove_colinear_vertices | ||||||
| 
 | 
 | ||||||
| @ -272,76 +272,23 @@ def read(filename: str, | |||||||
|                 pat.shapes.append(shape) |                 pat.shapes.append(shape) | ||||||
| 
 | 
 | ||||||
|             if isinstance(element, gdsii.elements.Path): |             if isinstance(element, gdsii.elements.Path): | ||||||
|                 if element.path_type == 0: |                 cap_map = {0: Path.Cap.Flush, | ||||||
|                     #cap = Path.Cap.Flush |                            1: Path.Cap.Circle, | ||||||
|                     extension = 0.0 |                            2: Path.Cap.Square, | ||||||
|                 elif element.path_type in (1, 4): |                           #3: custom? | ||||||
|                     raise PatternError('Round-ended and custom paths (types 1 and 4) are not implemented yet') |                           } | ||||||
|                 elif element.path_type == 2: |                 if element.path_type in cap_map: | ||||||
|                     extension = element.width / 2 |                     cap = cap_map[element.path_type] | ||||||
|                 else: |                 else: | ||||||
|                     raise PatternError('Unrecognized path type: {}'.format(element.path_type)) |                     raise PatternError('Unrecognized path type: {}'.format(element.path_type)) | ||||||
| 
 | 
 | ||||||
|                 if element.width == 0: |  | ||||||
|                     continue |  | ||||||
| 
 |  | ||||||
|                 v = remove_colinear_vertices(numpy.array(element.xy, dtype=float), closed_path=False) |  | ||||||
|                 dv = numpy.diff(v, axis=0) |  | ||||||
|                 dvdir = dv / numpy.sqrt((dv * dv).sum(axis=1))[:, None] |  | ||||||
|                 perp = dvdir[:, ::-1] * [[1, -1]] * element.width / 2 |  | ||||||
| 
 |  | ||||||
|                 # add extension |  | ||||||
|                 v[0] -= dvdir[0] * extension |  | ||||||
|                 v[-1] += dvdir[-1] * extension |  | ||||||
| 
 |  | ||||||
|                 # Find intersections of expanded sides |  | ||||||
|                 As = numpy.stack((dv[:-1], -dv[1:]), axis=2) |  | ||||||
|                 bs = v[1:-1] - v[:-2] + perp[1:] - perp[:-1] |  | ||||||
|                 ds = v[1:-1] - v[:-2] - perp[1:] + perp[:-1] |  | ||||||
| 
 |  | ||||||
|                 rp = numpy.linalg.solve(As, bs)[:, 0, None] |  | ||||||
|                 rn = numpy.linalg.solve(As, ds)[:, 0, None] |  | ||||||
| 
 |  | ||||||
|                 intersection_p = v[:-2] + rp * dv[:-1] + perp[:-1] |  | ||||||
|                 intersection_n = v[:-2] + rn * dv[:-1] - perp[:-1] |  | ||||||
| 
 |  | ||||||
|                 towards_perp = (dv[1:] * perp[:-1]).sum(axis=1) > 0 # path bends towards previous perp? |  | ||||||
| #               straight = (dv[1:] * perp[:-1]).sum(axis=1) == 0    # path is straight |  | ||||||
|                 acute = (dv[1:] * dv[:-1]).sum(axis=1) < 0          # angle is acute? |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                 o0 = [v[0] + perp[0]] |  | ||||||
|                 o1 = [v[0] - perp[0]] |  | ||||||
|                 for i in range(dv.shape[0] - 1): |  | ||||||
|                     if towards_perp[i]: |  | ||||||
|                         o0.append(intersection_p[i]) |  | ||||||
|                         if acute[i]: |  | ||||||
|                             o1.append(intersection_n[i]) |  | ||||||
|                         else: |  | ||||||
|                             # Opposite is >270 |  | ||||||
|                             pt0 = v[i + 1] - perp[i + 0] + dvdir[i + 0] * element.width / 2 |  | ||||||
|                             pt1 = v[i + 1] - perp[i + 1] - dvdir[i + 1] * element.width / 2 |  | ||||||
|                             o1 += [pt0, pt1] |  | ||||||
|                     else: |  | ||||||
|                         o1.append(intersection_n[i]) |  | ||||||
|                         if acute[i]: |  | ||||||
|                             # > 270 |  | ||||||
|                             pt0 = v[i + 1] + perp[i + 0] + dvdir[i + 0] * element.width / 2 |  | ||||||
|                             pt1 = v[i + 1] + perp[i + 1] - dvdir[i + 1] * element.width / 2 |  | ||||||
|                             o0 += [pt0, pt1] |  | ||||||
|                         else: |  | ||||||
|                             o0.append(intersection_p[i]) |  | ||||||
|                 o0.append(v[-1] + perp[-1]) |  | ||||||
|                 o1.append(v[-1] - perp[-1]) |  | ||||||
|                 verts = numpy.vstack((o0, o1[::-1])) |  | ||||||
| 
 |  | ||||||
|                 if use_dtype_as_dose: |                 if use_dtype_as_dose: | ||||||
|                     shape = Polygon(vertices=verts, |                     shape = Path(vertices=element.xy, | ||||||
|                                     dose=element.data_type, |                                  dose=element.data_type, | ||||||
|                                     layer=element.layer) |                                  layer=element.layer) | ||||||
|                 else: |                 else: | ||||||
|                     shape = Polygon(vertices=verts, |                     shape = Path(vertices=element.xy, | ||||||
|                                     layer=(element.layer, element.data_type)) |                                  layer=(element.layer, element.data_type)) | ||||||
|                 if clean_vertices: |                 if clean_vertices: | ||||||
|                     try: |                     try: | ||||||
|                         shape.clean_vertices() |                         shape.clean_vertices() | ||||||
|  | |||||||
| @ -153,7 +153,7 @@ class Arc(Shape): | |||||||
|         self.width = width |         self.width = width | ||||||
|         self.offset = offset |         self.offset = offset | ||||||
|         self.rotation = rotation |         self.rotation = rotation | ||||||
|         [self.mirror(a) for a in a, do in enumerate(mirrored) if do] |         [self.mirror(a) for a, do in enumerate(mirrored) if do] | ||||||
|         self.layer = layer |         self.layer = layer | ||||||
|         self.dose = dose |         self.dose = dose | ||||||
|         self.poly_num_points = poly_num_points |         self.poly_num_points = poly_num_points | ||||||
|  | |||||||
| @ -92,7 +92,7 @@ class Ellipse(Shape): | |||||||
|         self.radii = radii |         self.radii = radii | ||||||
|         self.offset = offset |         self.offset = offset | ||||||
|         self.rotation = rotation |         self.rotation = rotation | ||||||
|         [self.mirror(a) for a in a, do in enumerate(mirrored) if do] |         [self.mirror(a) for a, do in enumerate(mirrored) if do] | ||||||
|         self.layer = layer |         self.layer = layer | ||||||
|         self.dose = dose |         self.dose = dose | ||||||
|         self.poly_num_points = poly_num_points |         self.poly_num_points = poly_num_points | ||||||
|  | |||||||
| @ -127,7 +127,7 @@ class Path(Shape): | |||||||
|         self.width = width |         self.width = width | ||||||
|         self.cap = cap |         self.cap = cap | ||||||
|         self.rotate(rotation) |         self.rotate(rotation) | ||||||
|         [self.mirror(a) for a in a, do in enumerate(mirrored) if do] |         [self.mirror(a) for a, do in enumerate(mirrored) if do] | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def travel(travel_pairs: Tuple[Tuple[float, float]], |     def travel(travel_pairs: Tuple[Tuple[float, float]], | ||||||
| @ -142,11 +142,12 @@ class Path(Shape): | |||||||
|         """ |         """ | ||||||
|         TODO |         TODO | ||||||
| 
 | 
 | ||||||
|         :param rotation: Rotation counterclockwise, in radians | 
 | ||||||
|         :param offset: Offset, default (0, 0) |         :param offset: Offset, default (0, 0) | ||||||
|  |         :param rotation: Rotation counterclockwise, in radians | ||||||
|         :param layer: Layer, default 0 |         :param layer: Layer, default 0 | ||||||
|         :param dose: Dose, default 1.0 |         :param dose: Dose, default 1.0 | ||||||
|         :return: A Polygon object containing the requested square |         :return: The resulting Path object | ||||||
|         """ |         """ | ||||||
|         direction = numpy.array([1, 0]) |         direction = numpy.array([1, 0]) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| from typing import List | from typing import List, Tuple | ||||||
| import copy | import copy | ||||||
| import numpy | import numpy | ||||||
| from numpy import pi | from numpy import pi | ||||||
| @ -82,7 +82,7 @@ class Polygon(Shape): | |||||||
|         self.vertices = vertices |         self.vertices = vertices | ||||||
|         self.offset = offset |         self.offset = offset | ||||||
|         self.rotate(rotation) |         self.rotate(rotation) | ||||||
|         [self.mirror(a) for a in a, do in enumerate(mirrored) if do] |         [self.mirror(a) for a, do in enumerate(mirrored) if do] | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def square(side_length: float, |     def square(side_length: float, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user