def main(): filename = sys.argv[1] with open(filename, "rt") as f: xmltext = f.read() tree = ET.parse(filename) root = tree.getroot() polys = [] for child in root: tag = re.sub('^\{[^\}]*\}', "", child.tag, count=1) print(tag) if tag == "path": path = child.attrib['d'].strip().split(" ") process_path(path, polys) # Dump polygon details for p in polys: (minx, miny, maxx, maxy) = extents(p) print("Polygon %d: from (%d,%d) to (+%d,+%d), Orient: %s" % (p.id, minx, miny, maxx - minx, maxy - miny, "Outer" if pyclipper.Orientation(p.path) else "Inner")) for p in polys: if pyclipper.Orientation(p.path): # This polygon is interior print("\nInterior path: %r" % p) offset(p.path, -1.0) else: # This polygon is exterior print("\nExterior path: %r" % p) offset(p.path, 1.0)
def check_and_validate_polys(polys, tags, xxx_todo_changeme): ''' check so that the text poly is in the same direction, and also filter some invalid polygons :param polys: :param tags: :return: ''' (h, w) = xxx_todo_changeme if polys.shape[0] == 0: return [], [] polys[:, :, 0] = np.clip(polys[:, :, 0], 0, w - 1) polys[:, :, 1] = np.clip(polys[:, :, 1], 0, h - 1) validated_polys = [] validated_tags = [] for poly, tag in zip(polys, tags): if abs(pyclipper.Area(poly)) < 1: continue #clockwise if pyclipper.Orientation(poly): poly = poly[::-1] validated_polys.append(poly) validated_tags.append(tag) return np.array(validated_polys), np.array(validated_tags)
def orient_path(path, dir): orient = pyclipper.Orientation(path) path = pyclipper.scale_to_clipper(path, SCALING_FACTOR) if orient != dir: path = pyclipper.ReversePath(path) path = pyclipper.scale_from_clipper(path, SCALING_FACTOR) return path
def _identify_convex_points(path): # Make sure contour is wound in a clockwise order if not pyclipper.Orientation(path): path.reverse() point_iter = iter(path) prev_point1 = next(point_iter) prev_point2 = next(point_iter) for point in point_iter: # Calculate d value to find winding order x, y = point x1, y1 = prev_point1 x2, y2 = prev_point2 d_val = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1) # If d is zero then the point lies on the same tangent as the previous line segment # If d is less than zero then the point is concave if d_val < 0: turtle.penup() turtle.setpos(x2 - 5, y2) turtle.pendown() turtle.setpos(x2 + 5, y2) turtle.penup() turtle.setpos(x2, y2 - 5) turtle.pendown() turtle.setpos(x2, y2 + 5) # Shift points prev_point1 = prev_point2 prev_point2 = point
def __init__(self, contour): # gather the point data pointPen = ContourPointDataPen() contour.drawPoints(pointPen) points = pointPen.getData() reversedPoints = _reversePoints(points) # gather segments self.segments = _convertPointsToSegments(points) # only calculate once all the flat points. # it seems to have some tiny difference and its a lot faster # if the flat points are calculated from the reversed input points. self.reversedSegments = _convertPointsToSegments(reversedPoints, willBeReversed=True) # simple reverse the flat points and store them in the reversedSegments index = 0 for segment in self.segments: otherSegment = self.reversedSegments[index] otherSegment.flat = segment.getReversedFlatPoints() index -= 1 # get the direction; returns True if counter-clockwise, False otherwise self.clockwise = not pyclipper.Orientation(points) # store the gathered data if self.clockwise: self.clockwiseSegments = self.segments self.counterClockwiseSegments = self.reversedSegments else: self.clockwiseSegments = self.reversedSegments self.counterClockwiseSegments = self.segments # flag indicating if the contour has been used self.used = False
def __init__(self, pointList): if pointList[0] == pointList[-1]: del pointList[-1] self.clockwise = not pyclipper.Orientation(pointList) self.segments = [ OutputSegment(segmentType="flat", points=[point]) for point in pointList ]
def reord_layers(layers): for layer in layers: if len(layer) > 1: for poly1_index in range(len(layer)-1): if poly1_in_poly2(layer[poly1_index+1], layer[poly1_index]): layer.insert(0, layer.pop(poly1_index)) if poly1_in_poly2(layer[0], layer[len(layer)-1]): layer.insert(0, layer.pop(len(layer)-1)) for layer in layers: for poly_dex in range(len(layer)): if poly_dex == 0: if not pyclipper.Orientation(layer[poly_dex]): pyclipper.ReversePath(layer[poly_dex]) else: if pyclipper.Orientation(layer[poly_dex]): pyclipper.ReversePath(layer[poly_dex]) return layers
def order_clipped(polygons): hulls = [] holes = [] for poly in polygons: if pyclipper.Orientation(poly): hulls.append(poly) else: holes.append(poly) return hulls, holes
def reverse_points(self): """ If orientation is clockwise, convert to counter-clockwise. """ sc = constants.CLIPPER_SCALE pts = st(self.points, sc) if pyclipper.Orientation(pts) is False: reverse_poly = pyclipper.ReversePath(pts) solution = pyclipper.SimplifyPolygon(reverse_poly) else: solution = pyclipper.SimplifyPolygon(pts) self.points = sf(solution, sc)[0] return self
def reverse_points(pts): """ If orientation is clockwise, convert to counter-clockwise. """ points = [] sc = constants.CLIPPER_SCALE for poly in st(pts, sc): if pyclipper.Orientation(poly) is False: reverse_poly = pyclipper.ReversePath(poly) solution = pyclipper.SimplifyPolygon(reverse_poly) else: solution = pyclipper.SimplifyPolygon(poly) points.extend(solution) return points
def create_merged_points(self): """ """ from spira.gdsii.utils import scale_polygon_up as spu from spira.gdsii.utils import scale_polygon_down as spd polygons = spu(self.points) self.points = [] for poly in polygons: if pyclipper.Orientation(poly) is False: reverse_poly = pyclipper.ReversePath(poly) solution = pyclipper.SimplifyPolygon(reverse_poly) else: solution = pyclipper.SimplifyPolygon(poly) for sol in solution: self.points.append(sol) self.points = bool_operation(subj=self.points, method='union') self.points = spd(self.points) return self
def union(self): if not isinstance(self.raw_points[0][0], np.ndarray): raise TypeError("poly must be a 3D list") cc_poly = list() for poly in self.raw_points: if pyclipper.Orientation(poly) is False: reverse_poly = pyclipper.ReversePath(poly) cc_poly.append(reverse_poly) else: cc_poly.append(poly) union = utils.angusj(subj=cc_poly, method='union') points = pyclipper.CleanPolygons(union) if not isinstance(points[0][0], list): raise TypeError("poly must be a 3D list") return points
def test_orientation(self): self.assertFalse(pyclipper.Orientation(PATH_SUBJ_1)) self.assertTrue(pyclipper.Orientation(PATH_SUBJ_1[::-1]))
def test_orientation(self): with self.assertWarns(DeprecationWarning): pyclipper.Orientation(PATH_SUBJ_1)
def _generate_offset_contours(layer_slice, contour_offset): clipper_scale_factor = 10000 # Make sure that this layer is 2 dimensional prepped_slice, _ = layer_slice.to_planar( ) # 2nd tuple component is map to convert 2d path back to 3d path # Prepare the polygon for input to clipper for section in prepped_slice.polygons_full: # Add this polygons exterior outline = list(section.exterior.coords) source_polygon = pyclipper.scale_to_clipper(outline, clipper_scale_factor) clipper_object = pyclipper.PyclipperOffset() clipper_object.AddPath( source_polygon, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) # JT_MITER #JT_ROUND # Add this polygons interior sections for interior in section.interiors: hole_polygon = pyclipper.scale_to_clipper(list(interior.coords), clipper_scale_factor) clipper_object.AddPath(hole_polygon, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) # Offset each contour contours = [] hole_contours = [] for i in range(200): contour_layer = [] hole_contour_layer = [] solution = clipper_object.Execute( -(contour_offset * clipper_scale_factor) * i) # Check whether any contours were returned if len(solution) == 0: break # Convert contour points back to floats contour_sets = pyclipper.scale_from_clipper(solution, clipper_scale_factor) # Iterate over each of the contour groups for contour in contour_sets: # Add first point to end of path to close the loop contour.append(contour[0]) # Simplify contour contour = _simplify_path(contour) # Check if this is a hole: not_a_hole = pyclipper.Orientation(contour) if not_a_hole: # Add generated contour to list of contours contour_layer.append(contour) else: # Reverse direction of this contour contour.reverse() # Add generated contour to list of holes hole_contour_layer.append(contour) # Add this layer of contours to the contours list contours.append(contour_layer) hole_contours.append(hole_contour_layer) # In reverse order add holes onto to contour layers #print(contours) #print(hole_contours) for hole in reversed(hole_contours): contours.append(hole) #print(contours) # Temporary debugging #turtle.tracer(False) turtle.colormode(255) #for i in range(len(contours)): # turtle.pencolor((i*30, i*30, 0)) # print(contours[5]) # _debug_draw_paths(contours[i]) #turtle.exitonclick() # Return the set of contours return contours