def test_triangulate_triangle(self): normal = stl.Vector3d(1, 1, 1) a = stl.Vector3d(1, 0, 0) b = stl.Vector3d(0, 1, 0) c = stl.Vector3d(0, 0, 1) expected = stl.Facet(normal, (a, b, c)) result = ZGraph.triangulate(normal, (a, b, c)) self.assertEqual(result[0], expected)
def test_triangulate_square(self): top_left_front = stl.Vector3d(0, 0, 2) top_right_front = stl.Vector3d(1, 0, 2) top_left_back = stl.Vector3d(0, 1, 2) top_right_back = stl.Vector3d(1, 1, 2) corners = [ top_left_front, top_left_back, top_right_back, top_right_front ] normal = stl.Vector3d(0, 0, 1) result = ZGraph.triangulate(normal, corners) self.assertEqual(len(result), 2)
def test_basic_steplike_yface(self): def f(x, y): return stl.Vector3d(x, y, 2 if abs(y) > 1 else 1) range_ = (-3, 3) y_series = TickSeries(range_, 3) graph = MockZGraph(f, range_, y_series) left_face = YFace(range_[0], stl.Vector3d(-1, 0, 0), False, graph) self.assertEqual(len(left_face.face), 6)
def test_basic_steplike_face(self): def f(x, y): return stl.Vector3d(x, y, 2 if abs(x) > 1 else 1) range_ = (-3, 3) x_series = TickSeries(range_, 3) graph = MockZGraph(f, range_, x_series) front_face = XFace(range_[0], stl.Vector3d(0, -1, 0), True, graph) self.assertEqual(len(front_face.face), 6)
def normal(v1, v2, v3): u1 = (v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]) u2 = (v3[0] - v1[0], v3[1] - v1[1], v3[2] - v1[2]) x = u1[1] * u2[2] - u1[2] * u2[1] y = u1[2] * u2[0] - u1[0] * u2[2] z = u1[0] * u2[1] - u1[1] * u2[0] try: u = GridSquare.__normalize(stl.Vector3d(x, y, z)) except ZeroVectorError: raise ValueError(("Couldn't calculate the normal to the vectors" + "%s and %s - are they colinear? " + "The triangle points are %s, %s and %s.") % (u1, u2, v1, v2, v3)) return u
def face(self): value_vectors = [self.f(x, self.y) for x in self.x_ticks] base_vectors = [stl.Vector3d(x, self.y, 0) for x in self.x_ticks] facets = [] for i in range(0, len(base_vectors) - 1): if self.backwards: points = [ base_vectors[i], value_vectors[i], value_vectors[i + 1], base_vectors[i + 1] ] else: points = [ base_vectors[i], base_vectors[i + 1], value_vectors[i + 1], value_vectors[i] ] facets = facets + self.triangulate(self.normal, points) return facets
def __normalize(v): size = sqrt(v[0]**2 + v[1]**2 + v[2]**2) if size == 0: raise ZeroVectorError( "Tried to normalize a vector with size zero: %s" % str(v)) return stl.Vector3d(v[0] / size, v[1] / size, v[2] / size)
def vector_f(self, x, y): return stl.Vector3d(x, y, self.f(x, y))
def __bottom(self): return self.triangulate( self.down, (stl.Vector3d(self.x_range[0], self.y_range[0], 0), stl.Vector3d(self.x_range[0], self.y_range[1], 0), stl.Vector3d(self.x_range[1], self.y_range[1], 0), stl.Vector3d(self.x_range[1], self.y_range[0], 0)))
class ZGraph(object): rightw = stl.Vector3d(1, 0, 0) leftw = stl.Vector3d(-1, 0, 0) backwards = stl.Vector3d(0, 1, 0) forwards = stl.Vector3d(0, -1, 0) up = stl.Vector3d(0, 0, 1) down = stl.Vector3d(0, 0, -1) def __init__(self, x_range, y_range, f, n): self.x_range = x_range self.y_range = y_range self.f = f self.x_series = TickSeries(x_range, n) self.y_series = TickSeries(y_range, n) def __grid_squares(self): for y1, y2 in self.y_series.pairs: for x1, x2 in self.x_series.pairs: yield GridSquare(*[ self.vector_f(*pair) for pair in [(x1, y1), (x2, y1), (x2, y2), (x1, y2)] ]) @property def __top(self): return [f for sq in self.__grid_squares() for f in sq.facets] @property def __bottom(self): return self.triangulate( self.down, (stl.Vector3d(self.x_range[0], self.y_range[0], 0), stl.Vector3d(self.x_range[0], self.y_range[1], 0), stl.Vector3d(self.x_range[1], self.y_range[1], 0), stl.Vector3d(self.x_range[1], self.y_range[0], 0))) def vector_f(self, x, y): return stl.Vector3d(x, y, self.f(x, y)) @property def __front(self): return XFace(self.y_range[0], self.forwards, True, self).face @property def __back(self): return XFace(self.y_range[1], self.backwards, False, self).face @property def __right(self): return YFace(self.x_range[1], self.rightw, True, self).face @property def __left(self): return YFace(self.x_range[0], self.leftw, False, self).face def solid_output(self): return stl.Solid(name="ZGraph", facets=self.__top + self.__bottom + self.__front + self.__right + self.__back + self.__left) @staticmethod def triangulate(normal, vertices): if len(vertices) < 3: return [] facet1 = stl.Facet(normal, vertices[:3]) remaining_facets = vertices[:1] + vertices[2:] return [facet1] + ZGraph.triangulate(normal, remaining_facets)
def test_solid_output_for_simple_graph(self): def simple(x, y): if x > 0.5 and y > 0.5: return 2 else: return 1 graph = ZGraph((0, 1), (0, 1), simple, 1) top_left_front = stl.Vector3d(0, 0, 1) top_right_front = stl.Vector3d(1, 0, 1) top_left_back = stl.Vector3d(0, 1, 1) top_right_back = stl.Vector3d(1, 1, 2) bottom_left_front = stl.Vector3d(0, 0, 0) bottom_right_front = stl.Vector3d(1, 0, 0) bottom_left_back = stl.Vector3d(0, 1, 0) bottom_right_back = stl.Vector3d(1, 1, 0) top = [ stl.Facet(stl.Vector3d(0, -1 / sqrt(2), 1 / sqrt(2)), [top_left_front, top_right_front, top_right_back]), stl.Facet(stl.Vector3d(-1 / sqrt(2), 0, 1 / sqrt(2)), [top_left_front, top_right_back, top_left_back]), ] bottom = ZGraph.triangulate(stl.Vector3d(0, 0, -1), (bottom_left_front, bottom_left_back, bottom_right_back, bottom_right_front)) front = ZGraph.triangulate(stl.Vector3d(0, -1, 0), (bottom_left_front, bottom_right_front, top_right_front, top_left_front)) right = ZGraph.triangulate(stl.Vector3d(1, 0, 0), (bottom_right_front, bottom_right_back, top_right_back, top_right_front)) back = ZGraph.triangulate(stl.Vector3d(0, 1, 0), (bottom_left_back, top_left_back, top_right_back, bottom_right_back)) left = ZGraph.triangulate(stl.Vector3d(-1, 0, 0), (bottom_left_front, top_left_front, top_left_back, bottom_left_back)) facets = top + bottom + front + right + back + left expected = stl.Solid("ZGraph", facets) self.assertEqual(graph.solid_output(), expected)
def test_solid_output_for_const_graph(self): def const_2(x, y): return 2 graph = ZGraph((0, 1), (0, 1), const_2, 1) top_left_front = stl.Vector3d(0, 0, 2) top_right_front = stl.Vector3d(1, 0, 2) top_left_back = stl.Vector3d(0, 1, 2) top_right_back = stl.Vector3d(1, 1, 2) bottom_left_front = stl.Vector3d(0, 0, 0) bottom_right_front = stl.Vector3d(1, 0, 0) bottom_left_back = stl.Vector3d(0, 1, 0) bottom_right_back = stl.Vector3d(1, 1, 0) top = ZGraph.triangulate( stl.Vector3d(0, 0, 1), (top_left_front, top_right_front, top_right_back, top_left_back)) bottom = ZGraph.triangulate(stl.Vector3d(0, 0, -1), (bottom_left_front, bottom_left_back, bottom_right_back, bottom_right_front)) front = ZGraph.triangulate(stl.Vector3d(0, -1, 0), (bottom_left_front, bottom_right_front, top_right_front, top_left_front)) right = ZGraph.triangulate(stl.Vector3d(1, 0, 0), (bottom_right_front, bottom_right_back, top_right_back, top_right_front)) back = ZGraph.triangulate(stl.Vector3d(0, 1, 0), (bottom_left_back, top_left_back, top_right_back, bottom_right_back)) left = ZGraph.triangulate(stl.Vector3d(-1, 0, 0), (bottom_left_front, top_left_front, top_left_back, bottom_left_back)) facets = top + bottom + front + right + back + left expected = stl.Solid("ZGraph", facets) self.assertEqual(graph.solid_output(), expected)
def f(x, y): return stl.Vector3d(x, y, 2 if abs(y) > 1 else 1)