Change GridRepetition rotation/mirrored/scale properties so that they consistently apply only to the individual instances; the rotate()/mirror()/scale_by() functions apply to the full array. Add *_elements() versions of the functions
This commit is contained in:
parent
64b8e4dec8
commit
0db70d2c50
@ -404,7 +404,7 @@ def _aref_to_gridrep(element: gdsii.elements.ARef) -> GridRepetition:
|
|||||||
rotation = 0
|
rotation = 0
|
||||||
offset = numpy.array(element.xy[0])
|
offset = numpy.array(element.xy[0])
|
||||||
scale = 1
|
scale = 1
|
||||||
mirror_signs = numpy.ones(2)
|
mirror_across_x = False
|
||||||
|
|
||||||
if element.strans is not None:
|
if element.strans is not None:
|
||||||
if element.mag is not None:
|
if element.mag is not None:
|
||||||
@ -419,15 +419,11 @@ def _aref_to_gridrep(element: gdsii.elements.ARef) -> GridRepetition:
|
|||||||
raise PatternError('Absolute rotation is not implemented yet!')
|
raise PatternError('Absolute rotation is not implemented yet!')
|
||||||
# Bit 0 means mirror x-axis
|
# Bit 0 means mirror x-axis
|
||||||
if get_bit(element.strans, 15 - 0):
|
if get_bit(element.strans, 15 - 0):
|
||||||
mirror_signs[1] = -1
|
mirror_across_x = True
|
||||||
|
|
||||||
counts = [element.cols, element.rows]
|
counts = [element.cols, element.rows]
|
||||||
vec_a0 = element.xy[1] - offset
|
a_vector = (element.xy[1] - offset) / counts[0]
|
||||||
vec_b0 = element.xy[2] - offset
|
b_vector = (element.xy[2] - offset) / counts[1]
|
||||||
|
|
||||||
a_vector = numpy.dot(rotation_matrix_2d(-rotation), vec_a0 / scale / counts[0]) * mirror_signs
|
|
||||||
b_vector = numpy.dot(rotation_matrix_2d(-rotation), vec_b0 / scale / counts[1]) * mirror_signs
|
|
||||||
|
|
||||||
|
|
||||||
gridrep = GridRepetition(pattern=None,
|
gridrep = GridRepetition(pattern=None,
|
||||||
a_vector=a_vector,
|
a_vector=a_vector,
|
||||||
@ -437,7 +433,7 @@ def _aref_to_gridrep(element: gdsii.elements.ARef) -> GridRepetition:
|
|||||||
offset=offset,
|
offset=offset,
|
||||||
rotation=rotation,
|
rotation=rotation,
|
||||||
scale=scale,
|
scale=scale,
|
||||||
mirrored=(mirror_signs[::-1] == -1))
|
mirrored=(mirror_across_x, False))
|
||||||
gridrep.identifier = element.struct_name
|
gridrep.identifier = element.struct_name
|
||||||
|
|
||||||
return gridrep
|
return gridrep
|
||||||
@ -450,13 +446,12 @@ def _subpatterns_to_refs(subpatterns: List[SubPattern or GridRepetition]
|
|||||||
encoded_name = subpat.pattern.name
|
encoded_name = subpat.pattern.name
|
||||||
|
|
||||||
# Note: GDS mirrors first and rotates second
|
# Note: GDS mirrors first and rotates second
|
||||||
mirror_x, extra_angle = normalize_mirror(subpat.mirrored)
|
mirror_across_x, extra_angle = normalize_mirror(subpat.mirrored)
|
||||||
if isinstance(subpat, GridRepetition):
|
if isinstance(subpat, GridRepetition):
|
||||||
mirror_signs = [(-1 if mirror_x else 1), 1]
|
|
||||||
xy = numpy.array(subpat.offset) + [
|
xy = numpy.array(subpat.offset) + [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
numpy.dot(rotation_matrix_2d(subpat.rotation), subpat.a_vector * mirror_signs) * subpat.scale * subpat.a_count,
|
subpat.a_vector * subpat.a_count,
|
||||||
numpy.dot(rotation_matrix_2d(subpat.rotation), subpat.b_vector * mirror_signs) * subpat.scale * subpat.b_count,
|
subpat.b_vector * subpat.b_count,
|
||||||
]
|
]
|
||||||
ref = gdsii.elements.ARef(struct_name=encoded_name,
|
ref = gdsii.elements.ARef(struct_name=encoded_name,
|
||||||
xy=numpy.round(xy).astype(int),
|
xy=numpy.round(xy).astype(int),
|
||||||
@ -468,7 +463,7 @@ def _subpatterns_to_refs(subpatterns: List[SubPattern or GridRepetition]
|
|||||||
|
|
||||||
ref.angle = ((subpat.rotation + extra_angle) * 180 / numpy.pi) % 360
|
ref.angle = ((subpat.rotation + extra_angle) * 180 / numpy.pi) % 360
|
||||||
# strans must be non-None for angle and mag to take effect
|
# strans must be non-None for angle and mag to take effect
|
||||||
ref.strans = set_bit(0, 15 - 0, mirror_x)
|
ref.strans = set_bit(0, 15 - 0, mirror_across_x)
|
||||||
ref.mag = subpat.scale
|
ref.mag = subpat.scale
|
||||||
|
|
||||||
refs.append(ref)
|
refs.append(ref)
|
||||||
|
@ -39,10 +39,14 @@ class GridRepetition:
|
|||||||
pattern: 'Pattern'
|
pattern: 'Pattern'
|
||||||
|
|
||||||
_offset: numpy.ndarray
|
_offset: numpy.ndarray
|
||||||
_rotation: float
|
|
||||||
_dose: float
|
_dose: float
|
||||||
|
|
||||||
|
_rotation: float
|
||||||
|
''' Applies to individual instances in the grid, not the grid vectors '''
|
||||||
_scale: float
|
_scale: float
|
||||||
|
''' Applies to individual instances in the grid, not the grid vectors '''
|
||||||
_mirrored: List[bool]
|
_mirrored: List[bool]
|
||||||
|
''' Applies to individual instances in the grid, not the grid vectors '''
|
||||||
|
|
||||||
_a_vector: numpy.ndarray
|
_a_vector: numpy.ndarray
|
||||||
_b_vector: numpy.ndarray or None
|
_b_vector: numpy.ndarray or None
|
||||||
@ -287,7 +291,7 @@ class GridRepetition:
|
|||||||
|
|
||||||
def rotate_around(self, pivot: vector2, rotation: float) -> 'GridRepetition':
|
def rotate_around(self, pivot: vector2, rotation: float) -> 'GridRepetition':
|
||||||
"""
|
"""
|
||||||
Rotate around a point
|
Rotate the array around a point
|
||||||
|
|
||||||
:param pivot: Point to rotate around
|
:param pivot: Point to rotate around
|
||||||
:param rotation: Angle to rotate by (counterclockwise, radians)
|
:param rotation: Angle to rotate by (counterclockwise, radians)
|
||||||
@ -304,6 +308,19 @@ class GridRepetition:
|
|||||||
"""
|
"""
|
||||||
Rotate around (0, 0)
|
Rotate around (0, 0)
|
||||||
|
|
||||||
|
:param rotation: Angle to rotate by (counterclockwise, radians)
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
self.rotate_elements(rotation)
|
||||||
|
self.a_vector = numpy.dot(rotation_matrix_2d(rotation), self.a_vector)
|
||||||
|
if self.b_vector is not None:
|
||||||
|
self.b_vector = numpy.dot(rotation_matrix_2d(rotation), self.b_vector)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def rotate_elements(self, rotation: float) -> 'GridRepetition':
|
||||||
|
"""
|
||||||
|
Rotate each element around its origin
|
||||||
|
|
||||||
:param rotation: Angle to rotate by (counterclockwise, radians)
|
:param rotation: Angle to rotate by (counterclockwise, radians)
|
||||||
:return: self
|
:return: self
|
||||||
"""
|
"""
|
||||||
@ -317,13 +334,23 @@ class GridRepetition:
|
|||||||
:param axis: Axis to mirror across.
|
:param axis: Axis to mirror across.
|
||||||
:return: self
|
:return: self
|
||||||
"""
|
"""
|
||||||
self.mirrored[axis] = not self.mirrored[axis]
|
self.mirror_elements(axis)
|
||||||
self.rotation *= -1
|
|
||||||
self.a_vector[axis] *= -1
|
self.a_vector[axis] *= -1
|
||||||
if self.b_vector is not None:
|
if self.b_vector is not None:
|
||||||
self.b_vector[axis] *= -1
|
self.b_vector[axis] *= -1
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def mirror_elements(self, axis: int) -> 'GridRepetition':
|
||||||
|
"""
|
||||||
|
Mirror each element across an axis relative to its origin.
|
||||||
|
|
||||||
|
:param axis: Axis to mirror across.
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
self.mirrored[axis] = not self.mirrored[axis]
|
||||||
|
self.rotation *= -1
|
||||||
|
return self
|
||||||
|
|
||||||
def get_bounds(self) -> numpy.ndarray or None:
|
def get_bounds(self) -> numpy.ndarray or None:
|
||||||
"""
|
"""
|
||||||
Return a numpy.ndarray containing [[x_min, y_min], [x_max, y_max]], corresponding to the
|
Return a numpy.ndarray containing [[x_min, y_min], [x_max, y_max]], corresponding to the
|
||||||
@ -338,6 +365,18 @@ class GridRepetition:
|
|||||||
"""
|
"""
|
||||||
Scale the GridRepetition by a factor
|
Scale the GridRepetition by a factor
|
||||||
|
|
||||||
|
:param c: scaling factor
|
||||||
|
"""
|
||||||
|
self.scale_elements_by(c)
|
||||||
|
self.a_vector *= c
|
||||||
|
if self.b_vector is not None:
|
||||||
|
self.b_vector *= c
|
||||||
|
return self
|
||||||
|
|
||||||
|
def scale_elements_by(self, c: float) -> 'GridRepetition':
|
||||||
|
"""
|
||||||
|
Scale each element by a factor
|
||||||
|
|
||||||
:param c: scaling factor
|
:param c: scaling factor
|
||||||
"""
|
"""
|
||||||
self.scale *= c
|
self.scale *= c
|
||||||
|
Loading…
Reference in New Issue
Block a user