first commit

This commit is contained in:
Senad Uka
2017-11-07 09:23:57 +01:00
commit 0eee92660a
356 changed files with 747259 additions and 0 deletions

View File

@@ -0,0 +1 @@
__author__ = 'pivotal'

View File

@@ -0,0 +1,8 @@
class DXFError(Exception):
def __init__(self, message):
self.message = message
class OldDxfFormatException(Exception):
def __init__(self, message):
self.message = message

View File

@@ -0,0 +1,47 @@
from enum import Enum
class GraphDirection(Enum):
North = (0, 1)
NorthEast = (1, 1)
East = (1, 0)
SouthEast = (1, -1)
South = (0, -1)
SouthWest = (-1, -1)
West = (-1, 0)
NorthWest = (-1, 1)
@classmethod
def values(cls):
return [
cls.North.value,
cls.NorthEast.value,
cls.East.value,
cls.SouthEast.value,
cls.South.value,
cls.SouthWest.value,
cls.West.value,
cls.NorthWest.value
]
@classmethod
def ordinal_directions(cls):
return [
cls.North,
cls.East,
cls.South,
cls.West
]
def opposite_direction(self):
return {
GraphDirection.North: GraphDirection.South,
GraphDirection.NorthEast: GraphDirection.SouthWest,
GraphDirection.East: GraphDirection.West,
GraphDirection.SouthEast: GraphDirection.NorthWest,
GraphDirection.South: GraphDirection.North,
GraphDirection.SouthWest: GraphDirection.NorthEast,
GraphDirection.West: GraphDirection.East,
GraphDirection.NorthWest: GraphDirection.SouthEast
}[self]

View File

@@ -0,0 +1,68 @@
from helix.models.dxf.graph_direction import GraphDirection
class GraphNode(object):
def __init__(self, panel, x_spacing, y_spacing):
self.neighbors = {}
self.neighbors = {
GraphDirection.North: None,
GraphDirection.NorthEast: None,
GraphDirection.East: None,
GraphDirection.SouthEast: None,
GraphDirection.South: None,
GraphDirection.SouthWest: None,
GraphDirection.West: None,
GraphDirection.NorthWest: None
}
self.panel = panel
self.x_spacing = x_spacing
self.y_spacing = y_spacing
@property
def coordinate(self):
return self.panel.coordinate
def has_existing_neighbor(self, direction):
return self.neighbors.get(direction) is not None
def add_neighbor(self, other_node, direction):
if other_node is not None:
if direction:
self.neighbors[direction] = other_node
opposite_direction = direction.opposite_direction()
other_node.neighbors[opposite_direction] = self
def neighboring_nodes(self):
return [neighbor for neighbor in self.neighbors.values() if neighbor is not None]
def ordinal_neighbors(self):
neighbors = {}
for direction in GraphDirection.ordinal_directions():
if self.neighbors.get(direction):
neighbors[direction] = self.neighbors[direction]
return neighbors
def __hash__(self):
return self.panel.coordinate.__hash__()
def __repr__(self):
neighbors = {}
for key, value in self.neighbors.items():
if value is not None:
neighbors[key] = value.panel
return str(self.panel) + " - " + str(neighbors)
def __eq__(self, other):
if self is other:
return True
if not self.panel == other.panel and self.x_spacing != other.x_spacing and self.y_spacing != other.y_spacing:
return False
for key, value in self.neighbors.items():
other_neighbor = other.neighbors[key]
if value is None and other_neighbor is None:
continue
elif value is None or other_neighbor is None:
return False
elif value.panel != other_neighbor.panel:
return False
return True

View File

@@ -0,0 +1,41 @@
from helix.helpers.nodequadtree import Bounds, NodeQuadTree
class GraphNodeStore(list):
def __init__(self):
super().__init__()
self.variance = 0.2
self.first = True
self.quadTree = None
def add_node(self, node):
self.append(node)
if self.first:
self.left = self.right = node.coordinate.x
self.top = self.bottom = node.coordinate.y
self.first = False
else:
self.left = min(self.left, node.coordinate.x)
self.right = max(self.right, node.coordinate.x)
self.bottom = min(self.bottom, node.coordinate.y)
self.top = max(self.top, node.coordinate.y)
def distance_squared(self, node, coordinate):
dx = node.coordinate.x - coordinate.x
dy = node.coordinate.y - coordinate.y
return dx * dx + dy * dy
def find_coordinate(self, coordinate):
# create and populate the quadtree on first request
if self.quadTree is None:
self.quadTree = NodeQuadTree(1, Bounds(self.left, self.bottom, self.right - self.left, self.top - self.bottom), self.variance)
for node in self:
self.quadTree.insert(node)
del self[:]
possibilities = self.quadTree.retrieve(coordinate)
for node in possibilities:
if self.distance_squared(node, coordinate) <= self.variance ** 2:
return node
else:
return None

117
helix/models/dxf/polygon.py Normal file
View File

@@ -0,0 +1,117 @@
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