Пример #1
0
def _line(pieces):
    if len(pieces) != 7:
        raise PartError("Invalid line data")
    colour = colour_from_str(pieces[0])
    point1 = map(float, pieces[1:4])
    point2 = map(float, pieces[4:7])
    return Line(Colour(colour), Vector(*point1), Vector(*point2))
Пример #2
0
def get_bounding_box(points):
    return BoudingBox(
        Vector(min(p.x for p in points), min(p.y for p in points),
               min(p.z for p in points)),
        Vector(max(p.x for p in points), max(p.y for p in points),
               max(p.z for p in points)),
    )
Пример #3
0
    def _write_triangle(self, v1, v2, v3):
        self.minimum = Vector(min(self.minimum.x, v1.x, v2.x, v3.x),
                              min(self.minimum.y, -v1.y, -v2.y, -v3.y),
                              min(self.minimum.z, v1.z, v2.z, v3.z))
        self.maximum = Vector(max(self.maximum.x, v1.x, v2.x, v3.x),
                              max(self.maximum.y, -v1.y, -v2.y, -v3.y),
                              max(self.maximum.z, v1.z, v2.z, v3.z))
        #normal vector = cross product of any two of the edges
        #vec1 = p1-p2
        vec1 = numpy.matrix([v1.x - v2.x, v1.y - v2.y, v1.z - v2.z])
        #vec2 = p1-p3
        #vec2 = numpy.matrix([v1.x-v3.x,v1.y-v3.y,v1.z-v3.z])
        vec2 = numpy.matrix([v2.x - v3.x, v2.y - v3.y, v2.z - v3.z])
        #vec2 = numpy.matrix([v3.x-v1.x,v3.y-v1.y,v3.z-v1.z])

        normal_vector = numpy.cross(vec1, vec2)
        self.stl_file.write("facet normal %1.3f %1.3f %1.3f\n"
                            "\touter loop\n"
                            "\t\tvertex %1.3f %1.3f %1.3f\n"
                            "\t\tvertex %1.3f %1.3f %1.3f\n"
                            "\t\tvertex %1.3f %1.3f %1.3f\n"
                            "\tendloop\n"
                            "endfacet\n" %
                            (normal_vector.item(0), normal_vector.item(1),
                             normal_vector.item(2), v1.x, -v1.y, v1.z, v2.x,
                             -v2.y, v2.z, v3.x, -v3.y, v3.z))
Пример #4
0
 def __init__(self, parts, pov_file):
     self.parts = parts
     self.pov_file = pov_file
     self.lights = []
     self.minimum = Vector(0, 0, 0)
     self.maximum = Vector(0, 0, 0)
     self.warnings = []
Пример #5
0
    def __init__(self, parts, pov_file):

        self.parts = parts
        self.pov_file = pov_file
        self.lights = []
        self.minimum = Vector(0, 0, 0)
        self.maximum = Vector(0, 0, 0)
        self.bbox_cache = {}
Пример #6
0
def _triangle(pieces):
    if len(pieces) != 10:
        raise PartError("Invalid triangle data")
    colour = colour_from_str(pieces[0])
    point1 = map(float, pieces[1:4])
    point2 = map(float, pieces[4:7])
    point3 = map(float, pieces[7:10])
    return Triangle(Colour(colour), Vector(*point1), Vector(*point2),
                    Vector(*point3))
Пример #7
0
 def __init__(self, camera_position, axes, parts):
 
     self.parts = parts
     self.lights = []
     self.minimum = Vector(0, 0, 0)
     self.maximum = Vector(0, 0, 0)
     self.bbox_cache = {}
     self.camera_position = camera_position
     self.axes = axes
Пример #8
0
def _optional_line(pieces):
    if len(pieces) != 13:
        raise PartError("Invalid line data")
    colour = colour_from_str(pieces[0])
    point1 = map(float, pieces[1:4])
    point2 = map(float, pieces[4:7])
    point3 = map(float, pieces[7:10])
    point4 = map(float, pieces[10:13])
    return OptionalLine(Colour(colour), Vector(*point1), Vector(*point2),
                        Vector(*point3), Vector(*point4))
Пример #9
0
def _quadrilateral(pieces):
    if len(pieces) != 13:
        raise PartError("Invalid quadrilateral data")
    colour = colour_from_str(pieces[0])
    point1 = map(float, pieces[1:4])
    point2 = map(float, pieces[4:7])
    point3 = map(float, pieces[7:10])
    point4 = map(float, pieces[10:13])
    return Quadrilateral(Colour(colour), Vector(*point1), Vector(*point2),
                         Vector(*point3), Vector(*point4))
Пример #10
0
    def _polygons_from_objects(self,
                               model,
                               top_level_piece=None,
                               current=Current(Identity(), White.code, Vector(0, 0, 0))):
        # Extract polygons from objects, filtering out those behind the camera.
        polygons = []

        poly_handlers = {
            Piece: self._subpart_get_poly,
            Line: self._line_get_poly,
            Triangle: self._triangle_get_poly,
            Quadrilateral: self._quadrilateral_get_poly,
        }

        for obj in model.objects:
            if isinstance(obj, Piece) and obj.part == "LIGHT":
                continue
            try:
                args = (obj,
                        top_level_piece or obj,
                        current)
                poly = poly_handlers[type(obj)](*args)
            except KeyError:
                continue
            if poly:
                polygons.extend(poly)
            else:
                continue

        return polygons
Пример #11
0
 def write(self,
           model,
           current_matrix=Identity(),
           current_position=Vector(0, 0, 0),
           level=0):
     for obj in model.objects:
         if isinstance(obj, Piece):
             part = self.parts.part(code=obj.part)
             if part:
                 matrix = obj.matrix
                 self.write(
                     part, current_matrix * matrix,
                     current_position + current_matrix * obj.position,
                     level + 1)
             else:
                 sys.stderr.write("Part not found: %s\n" % obj.part)
         elif isinstance(obj, Triangle):
             p1 = current_matrix * obj.p1 + current_position
             p2 = current_matrix * obj.p2 + current_position
             p3 = current_matrix * obj.p3 + current_position
             if abs((p3 - p1).cross(p2 - p1)) != 0:
                 self._write_triangle(p1, p2, p3)
         elif isinstance(obj, Quadrilateral):
             p1 = current_matrix * obj.p1 + current_position
             p2 = current_matrix * obj.p2 + current_position
             p3 = current_matrix * obj.p3 + current_position
             p4 = current_matrix * obj.p4 + current_position
             if abs((p3 - p1).cross(p2 - p1)) != 0:
                 self._write_triangle(p1, p2, p3)
             if abs((p3 - p1).cross(p4 - p1)) != 0:
                 self._write_triangle(p3, p4, p1)
Пример #12
0
def vector_position(input_str):
    """ a type for comma separated vector """
    position = input_str.split(",")
    if len(position) != 3:
        raise argparse.ArgumentTypeError(
            "Expecting comma-separated elements for the position")
    return Vector(*map(float, position))
Пример #13
0
 def head(self, colour, angle=0, part=Head):
     """ Displacement from torso """
     displacement = self.matrix * Vector(0, -24, 0)
     piece = Piece(colour, self.position + displacement,
                   self.matrix * Identity().rotate(angle, YAxis), part,
                   self.group)
     self.pieces_info["head"] = piece
     return piece
Пример #14
0
 def __init__(self,
              position=Vector(0, 0, 0),
              matrix=Identity(),
              group=None):
     self.position = position
     self.matrix = matrix
     self.pieces_info = {}
     self.group = group
Пример #15
0
 def right_leg(self, colour, angle=0, part=LegRight):
     """" Add a right leg"""
     displacement = self.matrix * Vector(0, 44, 0)
     piece = Piece(colour, self.position + displacement,
                   self.matrix * Identity().rotate(angle, XAxis), part,
                   self.group)
     self.pieces_info["right leg"] = piece
     return piece
Пример #16
0
 def left_hand(self, left_arm, colour, angle=0, part=Hand):
     # Displacement from left hand
     displacement = left_arm.position + left_arm.matrix * Vector(4, 17, -9)
     matrix = left_arm.matrix * Identity().rotate(
         40, XAxis) * Identity().rotate(angle, ZAxis)
     piece = Piece(colour, displacement, matrix, part, self.group)
     self.pieces_info["left hand"] = piece
     return piece
Пример #17
0
 def _write_triangle(self, colour, *vectors):
     indent = 2
     assert len(vectors) == 3
     self.minimum = Vector(min(self.minimum.x, vectors[0].x, vectors[1].x, vectors[2].x),
                           min(self.minimum.y, -vectors[0].y, -vectors[1].y, -vectors[2].y),
                           min(self.minimum.z, vectors[0].z, vectors[1].z, vectors[2].z))
     self.maximum = Vector(max(self.maximum.x, vectors[0].x, vectors[1].x, vectors[2].x),
                           max(self.maximum.y, -vectors[0].y, -vectors[1].y, -vectors[2].y),
                           max(self.maximum.z, vectors[0].z, vectors[1].z, vectors[2].z))
     triangle = (
         vectors[0].x, vectors[0].y, vectors[0].z,
         vectors[1].x, vectors[1].y, vectors[1].z,
         vectors[2].x, vectors[2].y, vectors[2].z
     )
     lines = ["triangle", "{", POV_FORMAT_STRING_TRIANGLE % triangle]
     self.pov_file.write("\n".join(indent * " " + x for x in lines))
     self._write_colour(colour, indent + 2)
     self.pov_file.write(" " * indent + "}\n\n")
Пример #18
0
 def right_hand(self, right_arm, colour, angle=0, part=Hand):
     # Displacement from right arm
     displacement = right_arm.position + right_arm.matrix * Vector(
         -4, 17, -9)
     matrix = right_arm.matrix * Identity().rotate(
         40, XAxis) * Identity().rotate(angle, ZAxis)
     piece = Piece(colour, displacement, matrix, part, self.group)
     self.pieces_info["right hand"] = piece
     return piece
Пример #19
0
 def left_shoe(self, left_leg, colour, angle=0, part=None):
     """ Add a shoe on the left"""
     if not part:
         return None
     # Displacement from left leg
     displacement = left_leg.position + left_leg.matrix * Vector(10, 28, 0)
     matrix = left_leg.matrix * Identity().rotate(angle, YAxis)
     piece = Piece(colour, displacement, matrix, part, self.group)
     return piece
Пример #20
0
 def left_arm(self, colour, angle=0, part=ArmLeft):
     """ Displacement from torso """
     displacement = self.matrix * Vector(15, 8, 0)
     piece = Piece(
         colour, self.position + displacement,
         self.matrix * Identity().rotate(-10, ZAxis) *
         Identity().rotate(angle, XAxis), part, self.group)
     self.pieces_info["left arm"] = piece
     return piece
Пример #21
0
 def project(self, distance):
     """
     project to screen
     px/c = x/(c + z)
     px = c * x / (c + z)
     """
     for point in self.points:
         self.projected.append(
             Vector((distance * point.x) / (distance + -point.z),
                    (distance * point.y) / (distance + -point.z), -point.z))
Пример #22
0
def get_coordinate_system(camera_position, look_at_position):
    """" get coordinate system of the view """
    system = CoordinateSystem()
    system.z = (camera_position - look_at_position)
    system.z.norm()
    system.x = UP_DIRECTION.cross(system.z)
    if abs(system.x) == 0.0:
        system.x = system.z.cross(Vector(1.0, 0, 0))
    system.x.norm()
    system.y = system.z.cross(system.x)
    return system
Пример #23
0
    def _write_triangle(self, v1, v2, v3, colour, indent=0):

        self.minimum = Vector(min(self.minimum.x, v1.x, v2.x, v3.x),
                              min(self.minimum.y, -v1.y, -v2.y, -v3.y),
                              min(self.minimum.z, v1.z, v2.z, v3.z))
        self.maximum = Vector(max(self.maximum.x, v1.x, v2.x, v3.x),
                              max(self.maximum.y, -v1.y, -v2.y, -v3.y),
                              max(self.maximum.z, v1.z, v2.z, v3.z))

        lines = [
            "triangle", "{",
            "  <%1.3f, %1.3f, %1.3f>, "
            "<%1.3f, %1.3f, %1.3f>, "
            "<%1.3f, %1.3f, %1.3f>\n" %
            (v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z)
        ]

        self.pov_file.write("\n".join(map(lambda x: indent * " " + x, lines)))
        self._write_colour(colour, indent + 2)
        self.pov_file.write(" " * indent + "}\n\n")
Пример #24
0
def test_add_piece():
    group1 = Group()
    group2 = Group()
    piece = Piece(White, Vector(0, 0, 0), Identity(), Brick1X1, group=group1)

    assert piece in group1.pieces
    assert piece not in group2.pieces

    group2.add_piece(piece)

    assert piece in group2.pieces
    assert piece not in group1.pieces
Пример #25
0
    def _write_triangle_old(self, v1, v2, v3):
        self.minimum = Vector(min(self.minimum.x, v1.x, v2.x, v3.x),
                              min(self.minimum.y, -v1.y, -v2.y, -v3.y),
                              min(self.minimum.z, v1.z, v2.z, v3.z))
        self.maximum = Vector(max(self.maximum.x, v1.x, v2.x, v3.x),
                              max(self.maximum.y, -v1.y, -v2.y, -v3.y),
                              max(self.maximum.z, v1.z, v2.z, v3.z))
        #normal vector = cross product of any two of the edges
        #vec1 = p1-p2
        vec1 = numpy.matrix([v1.x - v2.x, v1.y - v2.y, v1.z - v2.z])
        #vec2 = p1-p3
        #vec2 = numpy.matrix([v1.x-v3.x,v1.y-v3.y,v1.z-v3.z])
        vec2 = numpy.matrix([v2.x - v3.x, v2.y - v3.y, v2.z - v3.z])
        #vec2 = numpy.matrix([v3.x-v1.x,v3.y-v1.y,v3.z-v1.z])

        normal_vector = numpy.cross(vec1, vec2)

        #StlMesh_MeshTriangle (const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3, const Standard_Real Xn, const Standard_Real Yn, const Standard_Real Zn)
        self.occ_model.AddTriangle(vec1.item(0), vec1.item(1), vec1.item(2),
                                   vec2.item(0), vec2.item(1), vec2.item(2),
                                   normal_vector.item(0),
                                   normal_vector.item(1),
                                   normal_vector.item(2))
Пример #26
0
def _sub_file(pieces):
    if len(pieces) != 14:
        raise PartError("Invalid part data")
    colour = colour_from_str(pieces[0])
    position = list(map(float, pieces[1:4]))
    rows = [
        list(map(float, pieces[4:7])),
        list(map(float, pieces[7:10])),
        list(map(float, pieces[10:13]))
    ]
    part = pieces[13].upper()
    if re.search(ENDS_DOT_DAT, part):
        part = part[:-4]
    return Piece(Colour(colour), Vector(*position), Matrix(rows), part)
Пример #27
0
 def collides_with(self, other):
     bb1 = get_bounding_box(get_points(
         parts.part(code=self.part))) + Vector(*tuple(self.pos))
     bb2 = get_bounding_box(get_points(
         parts.part(code=other.part))) + Vector(*tuple(other.pos))
     return bounding_boxes_collide(bb1, bb2)
Пример #28
0
    return Vector(*map(float, position))


def get_model(ldraw_path):
    """" get model from ldraw path """
    config = get_config()
    parts = Parts(config['parts.lst'])
    try:
        model = Part(ldraw_path)
    except PartError:
        sys.stderr.write("Failed to read LDraw file: %s\n" % ldraw_path)
        sys.exit(1)
    return model, parts


UP_DIRECTION = Vector(0, -1.0, 0)


def get_coordinate_system(camera_position, look_at_position):
    """" get coordinate system of the view """
    system = CoordinateSystem()
    system.z = (camera_position - look_at_position)
    system.z.norm()
    system.x = UP_DIRECTION.cross(system.z)
    if abs(system.x) == 0.0:
        system.x = system.z.cross(Vector(1.0, 0, 0))
    system.x.norm()
    system.y = system.z.cross(system.x)
    return system

Пример #29
0
 def _polygons_from_objects(self, model, top_level_piece = None, current_colour = 15, current_matrix = Identity(),
                            current_position = Vector(0, 0, 0)):
 
     # Extract polygons from objects, filtering out those behind the camera.
     
     polygons = []
     c = self.camera_position
     x, y, z = self.axes
     
     for obj in model.objects:
     
         if isinstance(obj, Piece):
         
             if obj.part == "LIGHT":
                 continue
             
             colour = self._current_colour(obj.colour, current_colour)
             part = self.parts.part(code = obj.part)
             
             if part:
                 matrix = obj.matrix
                 polygons += self._polygons_from_objects(
                     part, top_level_piece or obj, colour,
                     current_matrix * matrix,
                     current_position + current_matrix * obj.position)
             else:
                 sys.stderr.write("Part not found: %s\n" % obj.part)
         
         elif isinstance(obj, Line):
         
             p1 = current_matrix * obj.p1 + current_position - c
             p2 = current_matrix * obj.p2 + current_position - c
             
             r1 = Vector(p1.dot(x), p1.dot(y), p1.dot(z))
             r2 = Vector(p2.dot(x), p2.dot(y), p2.dot(z))
             
             if r1.z >= 0 or r2.z >= 0:
                 continue
             
             colour = self._current_colour(obj.colour, current_colour)
             polygons.append(Polygon(min(r1.z, r2.z), [r1, r2], colour, top_level_piece))
         
         elif isinstance(obj, Triangle):
         
             p1 = current_matrix * obj.p1 + current_position - c
             p2 = current_matrix * obj.p2 + current_position - c
             p3 = current_matrix * obj.p3 + current_position - c
             
             if abs((p3 - p1).cross(p2 - p1)) == 0:
                 continue
             
             r1 = Vector(p1.dot(x), p1.dot(y), p1.dot(z))
             r2 = Vector(p2.dot(x), p2.dot(y), p2.dot(z))
             r3 = Vector(p3.dot(x), p3.dot(y), p3.dot(z))
             
             if r1.z >= 0 or r2.z >= 0 or r3.z >= 0:
                 continue
             
             colour = self._current_colour(obj.colour, current_colour)
             polygons.append(Polygon(min(r1.z, r2.z, r3.z), [r1, r2, r3], colour, top_level_piece))
         
         elif isinstance(obj, Quadrilateral):
         
             p1 = current_matrix * obj.p1 + current_position - c
             p2 = current_matrix * obj.p2 + current_position - c
             p3 = current_matrix * obj.p3 + current_position - c
             p4 = current_matrix * obj.p4 + current_position - c
             
             if abs((p3 - p1).cross(p2 - p1)) == 0:
                 continue
             if abs((p3 - p1).cross(p4 - p1)) == 0:
                 continue
             
             r1 = Vector(p1.dot(x), p1.dot(y), p1.dot(z))
             r2 = Vector(p2.dot(x), p2.dot(y), p2.dot(z))
             r3 = Vector(p3.dot(x), p3.dot(y), p3.dot(z))
             r4 = Vector(p4.dot(x), p4.dot(y), p4.dot(z))
             
             if r1.z >= 0 or r2.z >= 0 or r3.z >= 0 or r4.z >= 0:
                 continue
             
             colour = self._current_colour(obj.colour, current_colour)
             polygons.append(Polygon(min(r1.z, r2.z, r3.z, r4.z), [r1, r2, r3, r4], colour, top_level_piece))
     
     return polygons
Пример #30
0
    image_dimensions = match["image size"].split("x")
    if len(image_dimensions) != 2:
        sys.stderr.write(
            "Incorrect number of values specified for the image size: %s\n" %
            match["image size"])
        sys.exit(1)
    try:
        image_size = map(int, image_dimensions)
    except ValueError:
        sys.stderr.write(
            "Non-integer value specified for the image size: %s\n" %
            match["image size"])
        sys.exit(1)

    camera_position = Vector(*map(float, match["camera position"].split(",")))
    look_at_position = Vector(
        *map(float,
             match.get("look-at position", "0.0,0.0,0.0").split(",")))

    parts = Parts(parts_path)

    try:
        model = Part(ldraw_path)
    except PartError:
        sys.stderr.write("Failed to read LDraw file: %s\n" % ldraw_path)
        sys.exit(1)

    if match.has_key("sky"):
        background_colour = match["background colour"]
    else: