Skip to content
This repository has been archived by the owner on Aug 9, 2024. It is now read-only.

I add class Ellipse in gdspy, it is very useful #59

Closed
harrywang2018 opened this issue Jul 18, 2018 · 3 comments
Closed

I add class Ellipse in gdspy, it is very useful #59

harrywang2018 opened this issue Jul 18, 2018 · 3 comments

Comments

@harrywang2018
Copy link

Hi, based on class Round(), I add class Ellipse(), it is very usefule for me.
class Ellipse(PolygonSet):

__slots__ = 'layers', 'datatypes', 'polygons'

def __init__(self,
             center,
             radius_x,
             radius_y,
             inner_radius_x=0,
             inner_radius_y=0,
             initial_angle=0,
             final_angle=0,
             number_of_points=100,
             max_points=199,
             layer=0,
             datatype=0):
    radius=max(radius_x,radius_y)
    if isinstance(number_of_points, float):
        if inner_radius_x <= 0 and inner_radius_y<=0:
            if final_angle == initial_angle:
                number_of_points = int(
                    2 * radius * numpy.pi / number_of_points + 0.5)
            else:
                number_of_points = int(
                    abs(final_angle - initial_angle) * radius /
                    number_of_points + 0.5) + 2
        else:
            if final_angle == initial_angle:
                number_of_points = 2 * int(
                    2 * radius * numpy.pi / number_of_points + 0.5) + 2
            else:
                number_of_points = 2 * int(
                    abs(final_angle - initial_angle) * radius /
                    number_of_points + 0.5) + 2
    number_of_points = max(number_of_points, 3)
    pieces = int(numpy.ceil(number_of_points / float(max_points)))
    number_of_points = number_of_points // pieces
    self.layers = [layer] * pieces
    self.datatypes = [datatype] * pieces
    self.polygons = [
        numpy.zeros((number_of_points, 2)) for _ in range(pieces)
    ]
    if final_angle == initial_angle and pieces > 1:
        final_angle += 2 * numpy.pi
    angles = numpy.linspace(initial_angle, final_angle, pieces + 1)
    for ii in range(pieces):
        if angles[ii + 1] == angles[ii]:
            if inner_radius_x <= 0 and inner_radius_y<=0:
                angle = numpy.arange(
                    number_of_points) * 2.0 * numpy.pi / number_of_points
                self.polygons[ii][:, 0] = numpy.cos(angle)*radius_x
                self.polygons[ii][:, 1] = numpy.sin(angle)*radius_y
                self.polygons[ii] = (
                    self.polygons[ii] + numpy.array(center))
            else:
                n2 = number_of_points // 2
                n1 = number_of_points - n2
                angle = numpy.arange(n1) * 2.0 * numpy.pi / (n1 - 1.0)
                self.polygons[ii][:n1, 0] = (
                    numpy.cos(angle) * radius_x + center[0])
                self.polygons[ii][:n1, 1] = (
                    numpy.sin(angle) * radius_y + center[1])
                angle = numpy.arange(n2) * -2.0 * numpy.pi / (n2 - 1.0)
                self.polygons[ii][n1:, 0] = (
                    numpy.cos(angle) * inner_radius_x + center[0])
                self.polygons[ii][n1:, 1] = (
                    numpy.sin(angle) * inner_radius_y + center[1])
        else:
            if inner_radius_x <= 0 and inner_radius_y<=0:
                angle = numpy.linspace(angles[ii], angles[ii + 1],
                                       number_of_points - 1)
                self.polygons[ii][1:, 0] = numpy.cos(angle)* radius_x
                self.polygons[ii][1:, 1] = numpy.sin(angle)* radius_y
                self.polygons[ii] = (
                    self.polygons[ii]  + numpy.array(center))
            else:
                n2 = number_of_points // 2
                n1 = number_of_points - n2
                angle = numpy.linspace(angles[ii], angles[ii + 1], n1)
                self.polygons[ii][:n1, 0] = (
                    numpy.cos(angle) * radius_x + center[0])
                self.polygons[ii][:n1, 1] = (
                    numpy.sin(angle) * radius_y + center[1])
                angle = numpy.linspace(angles[ii + 1], angles[ii], n2)
                self.polygons[ii][n1:, 0] = (
                    numpy.cos(angle) * inner_radius_x + center[0])
                self.polygons[ii][n1:, 1] = (
                    numpy.sin(angle) * inner_radius_y + center[1])

def __str__(self):
    return ("Round ({} polygons, {} vertices, layers {}, datatypes "
            "{})").format(
                len(self.polygons), sum([len(p) for p in self.polygons]),
                list(set(self.layers)), list(set(self.datatypes)))
@heitzmann
Copy link
Owner

@harrywang2018 Thanks! I'll take a look and add it to the develop branch.

@heitzmann
Copy link
Owner

@harrywang2018 There is an issue with this simple approach of just changing the radii in each direction: the angle used in the expressions does not correspond to the angle measured from the center (as in the circular case).

I've proposed an implementation of Round that allows elliptical shapes taking this issue into account in 04c0ac3. Please take a look and let me know if this works for you.

@harrywang2018
Copy link
Author

@heitzmann ,thanks very very much!!!!!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants