118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
import math
|
|
from helix.functions import fequal
|
|
|
|
|
|
class Polygon(object):
|
|
def __init__(self, line=None, points=()):
|
|
if line:
|
|
self.points = [line.start, line.end]
|
|
elif points:
|
|
self.points = points
|
|
else:
|
|
self.points = []
|
|
|
|
def continues_with_line(self, line):
|
|
if not self.closed and line.start == self.points[-1]:
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def closed(self):
|
|
return len(self.points) != 1 and self.points[0] == self.points[-1]
|
|
|
|
def sorted_points(self):
|
|
return sorted(self.points, key=lambda x: x[0])
|
|
|
|
def determine_orientation(self):
|
|
points = self.sorted_points()
|
|
p1 = points[0]
|
|
other_points = sorted(points[1:], key=lambda x: (x[0] - p1[0]) ** 2 + (x[1] - p1[1]) ** 2)
|
|
p2 = other_points[1]
|
|
# other_points[0] is the point that (along with p1) defines the short edge of this rectangle
|
|
# other_points[1] defines the long edge of this rectangle
|
|
# other_points[2] is diagonally across from p1. Not useful for defining edges.
|
|
x = p2[0] - p1[0]
|
|
y = p2[1] - p1[1]
|
|
return math.degrees(math.atan2(y, x))
|
|
|
|
def __do_something_with_long_edges__(self, module, fn, pair_spacing):
|
|
def cmp_point(p1, p2, pair_spacing):
|
|
dx = p1[0] - p2[0]
|
|
dy = p1[1] - p2[1]
|
|
d = math.sqrt(dx * dx + dy * dy)
|
|
allowedVariance = 0.1
|
|
|
|
if pair_spacing is None:
|
|
return d < allowedVariance
|
|
else:
|
|
d = math.fabs(d - pair_spacing)
|
|
return d <= allowedVariance
|
|
|
|
p1 = self.points[0]
|
|
other_points = sorted(self.points[1:], key=lambda x: (x[0] - p1[0]) ** 2 + (x[1] - p1[1]) ** 2)
|
|
self_long_edges = [sorted([p1, other_points[1]],), sorted([other_points[0], other_points[2]],)]
|
|
|
|
p2 = module.points[0]
|
|
other_points = sorted(module.points[1:], key=lambda x: (x[0] - p2[0]) ** 2 + (x[1] - p2[1]) ** 2)
|
|
other_long_edges = [sorted([p2, other_points[1]],), sorted([other_points[0], other_points[2]],)]
|
|
|
|
for edge in self_long_edges:
|
|
for other_edge in other_long_edges:
|
|
if cmp_point(edge[0], other_edge[0], pair_spacing) and\
|
|
cmp_point(edge[1], other_edge[1], pair_spacing):
|
|
fn(self, module, edge, other_edge)
|
|
return True
|
|
|
|
return False
|
|
|
|
def shares_module_on_long_edge(self, module, pair_spacing):
|
|
def on_match_edges(this, other, this_edges, other_edges):
|
|
pass
|
|
|
|
return self.__do_something_with_long_edges__(module, on_match_edges, pair_spacing)
|
|
|
|
def consolidate_with(self, pair, pair_spacing):
|
|
def on_match_edges(this, other, this_edges, other_edges):
|
|
this.points.remove(this_edges[0])
|
|
this.points.remove(this_edges[1])
|
|
other.points.remove(other_edges[0])
|
|
other.points.remove(other_edges[1])
|
|
this.points += pair.points
|
|
|
|
self.__do_something_with_long_edges__(pair, on_match_edges,
|
|
pair_spacing)
|
|
|
|
def scale(self, scale_x=1, scale_y=1):
|
|
polygon = Polygon()
|
|
polygon.points = [(x * scale_x, y * scale_y) for x, y in self.points]
|
|
return polygon
|
|
|
|
def svg_points(self, array_size):
|
|
value_string = ""
|
|
if len(self.points) == 4:
|
|
p0 = self.points[0]
|
|
points = sorted(self.points, key=lambda x: (x[0] - p0[0]) ** 2 + (x[1] - p0[1]) ** 2)
|
|
sorted_points = [p0, points[1], points[3], points[2]]
|
|
else:
|
|
sorted_points = self.points
|
|
for point in sorted_points:
|
|
value_string += "%f,%f " % (point[0], array_size[1] - point[1])
|
|
return value_string
|
|
|
|
def __repr__(self):
|
|
return str([(round(p[0], 3), round(p[1], 3)) for p in self.points])
|
|
|
|
def __eq__(self, other):
|
|
if self is other:
|
|
return True
|
|
if not isinstance(other, self.__class__):
|
|
return False
|
|
if len(self.points) != len(other.points):
|
|
return False
|
|
for idx, point in enumerate(self.points):
|
|
other_point = other.points[idx]
|
|
for variable_index in range(len(point)):
|
|
if not fequal(point[variable_index], other_point[variable_index]):
|
|
return False
|
|
return True
|