From ab483fc9d46eee2a5f4f10be91fd6190b0353a2b Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Tue, 13 Nov 2018 23:32:26 -0800 Subject: [PATCH] Remove pyclipper dependency; remove shape.cut() --- README.md | 1 - masque/__init__.py | 1 - masque/shapes/polygon.py | 39 ++++++++++++++++++++++++++------ masque/shapes/shape.py | 49 ---------------------------------------- setup.py | 1 - 5 files changed, 32 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index d2b7e35..6851d70 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ E-beam doses, and the ability to output to multiple formats. Requirements: * python >= 3.5 (written and tested with 3.6) * numpy -* pyclipper * matplotlib (optional, used for visualization functions and text) * python-gdsii (optional, used for gdsii i/o) * svgwrite (optional, used for svg output) diff --git a/masque/__init__.py b/masque/__init__.py index e77b1e7..a2a744c 100644 --- a/masque/__init__.py +++ b/masque/__init__.py @@ -18,7 +18,6 @@ Dependencies: - numpy - - pyclipper - matplotlib [Pattern.visualize(...)] - python-gdsii [masque.file.gdsii] - svgwrite [masque.file.svgwrite] diff --git a/masque/shapes/polygon.py b/masque/shapes/polygon.py index 85282a4..9fd10be 100644 --- a/masque/shapes/polygon.py +++ b/masque/shapes/polygon.py @@ -2,8 +2,6 @@ from typing import List import copy import numpy from numpy import pi -import pyclipper -from pyclipper import scale_to_clipper, scale_from_clipper from . import Shape, normalized_shape_tuple from .. import PatternError @@ -185,11 +183,38 @@ class Polygon(Shape): :returns: self """ - self.vertices = scale_from_clipper( - pyclipper.CleanPolygon( - scale_to_clipper( - self.vertices - ))) + self.remove_colinear_vertices() return self + def remove_duplicate_vertices(self) -> 'Polygon' + ''' + Removes all consecutive duplicate (repeated) vertices. + + :returns: self + ''' + duplicates = (self.vertices == numpy.roll(self.vertices, 1, axis=0)).all(axis=1) + self.vertices = self.vertices[~duplicates] + return self + + def remove_colinear_vertices(self) -> 'Polygon' + ''' + Removes consecutive co-linear vertices. + + :returns: self + ''' + dv0 = numpy.roll(self.vertices, 1, axis=0) - self.vertices + dv1 = numpy.roll(dv0, -1, axis=0) + + # find cases where at least one coordinate is 0 in successive dv's + eq = dv1 == dv0 + aa_colinear = numpy.logical_and(eq, dv0 == 0).any(axis=1) + + # find cases where slope is equal + with numpy.errstate(divide='ignore', invalid='ignore'): # don't care about zeroes + slope_quotient = (dv0[:, 0] * dv1[:, 1]) / (dv1[:, 0] * dv0[:, 1]) + slopes_equal = numpy.abs(slope_quotient - 1) < 1e-14 + + colinear = numpy.logical_or(aa_colinear, slopes_equal) + self.vertices = self.vertices[~colinear] + return self diff --git a/masque/shapes/shape.py b/masque/shapes/shape.py index 3384353..13ffa28 100644 --- a/masque/shapes/shape.py +++ b/masque/shapes/shape.py @@ -3,9 +3,6 @@ from abc import ABCMeta, abstractmethod import copy import numpy -import pyclipper -from pyclipper import scale_to_clipper, scale_from_clipper - from .. import PatternError from ..utils import is_scalar, rotation_matrix_2d, vector2 @@ -369,49 +366,3 @@ class Shape(metaclass=ABCMeta): return manhattan_polygons - def cut(self, - cut_xs: numpy.ndarray = None, - cut_ys: numpy.ndarray = None - ) -> List['Polygon']: - """ - Decomposes the shape into a list of constituent polygons by polygonizing and - then cutting along the specified x and/or y coordinates. - - :param cut_xs: list of x-coordinates to cut along (e.g., [1, 1.4, 6]) - :param cut_ys: list of y-coordinates to cut along (e.g., [1, 3, 5.4]) - :return: List of Polygon objects - """ - from . import Polygon - - clipped_shapes = [] - for polygon in self.to_polygons(): - min_x, min_y = numpy.min(polygon.vertices, axis=0) - max_x, max_y = numpy.max(polygon.vertices, axis=0) - range_x = max_x - min_x - range_y = max_y - min_y - - 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,) - - for i in range(2): - for j in range(2): - clipper = pyclipper.Pyclipper() - clipper.AddPath(scale_to_clipper(polygon.vertices), pyclipper.PT_SUBJECT, True) - - 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 = polygon.copy() - poly.vertices = part - clipped_shapes.append(poly) - return clipped_shapes diff --git a/setup.py b/setup.py index b12a255..e3af502 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ setup(name='masque', packages=find_packages(), install_requires=[ 'numpy', - 'pyclipper', ], extras_require={ 'visualization': ['matplotlib'],