Example #1
0
def get_sub_triangles(triangle: Triangle):
    """
    Return the sub-triangles (central triangle and 3 corner triangles)
    resulting from connecting the mid-points of triangle's sides.

    Parameters:
    triangle -- The triangle to be split into sub-triangles.

    Return value:
    Length-2 tuple containing:
    -- The central triangle (Triangle class instance).
    -- The 3 corner triangles (length-3 tuple containing Triangle class
      instances).
    """
    central_triangle = Triangle(get_mid_point(triangle[0], triangle[1]),
                                get_mid_point(triangle[1], triangle[2]),
                                get_mid_point(triangle[2], triangle[0]))

    corner_triangles = (Triangle(triangle[0], central_triangle[0],
                                 central_triangle[2]),
                        Triangle(triangle[1], central_triangle[1],
                                 central_triangle[0]),
                        Triangle(triangle[2], central_triangle[2],
                                 central_triangle[1]))
    return (central_triangle, corner_triangles)
def get_main_triangle(side_len, margin_width) -> Triangle:
    """
    Return the main (outermost) triangle (an equilateral triangle with
    a horizontal base).
    """
    height = get_triangle_height(side_len)

    lower_left = Point(margin_width, margin_width)
    top = Point(margin_width + side_len / 2.0, margin_width + height)
    lower_right = Point(margin_width + side_len, margin_width)

    return Triangle(lower_left, top, lower_right)
Example #3
0
def cart_to_screen(points, size):
    """
    Convert Cartesian coordinates to screen coordinates.
    Arguments:
    points is a list of Point objects or a vertex-defined Triangle object
    size is a 2-tuple of the screen dimensions (width, height)
    Returns:
    A list of Point objects or a Triangle object, depending on the type of the input
    """
    if isinstance(points, Triangle):
        return Triangle(Point(points.a.x, size[1] - points.a.y),
                        Point(points.b.x, size[1] - points.b.y),
                        Point(points.c.x, size[1] - points.c.y))
    else:
        trans_points = [Point(p.x, size[1] - p.y) for p in points]
        return trans_points
Example #4
0
def parse_stl(filename):
    """Parse un fichier STL."""
    data = {
        'triangles': [],

        # Extremums
        'xmin': float('inf'),
        'xmax': float('-inf'),
        'ymin': float('inf'),
        'ymax': float('-inf'),
        'zmin': float('inf'),
        'zmax': float('-inf'),
    }

    file = open(filename, 'rb')
    parser = BinaryParser(file)
    parser.read_bytes(80)
    data['num_triangles'] = parser.read_uint32()
    print('Nombre de triangles :', data['num_triangles'])

    for _ in range(data['num_triangles']):
        # Vecteur normal
        parser.read_float(3)
        vertices = []
        for _ in range(3):
            vertex = Vertex(parser.read_float(3))
            data['xmin'], data['xmax'] = extremums(
                data['xmin'], data['xmax'], vertex.x)
            data['ymin'], data['ymax'] = extremums(
                data['ymin'], data['ymax'], vertex.y)
            data['zmin'], data['zmax'] = extremums(
                data['zmin'], data['zmax'], vertex.z)
            vertices.append(vertex)
        # Attribute byte count
        parser.read_uint16()
        triangle = Triangle(vertices)
        data['triangles'].append(triangle)
    file.close()

    return data
Example #5
0
    def get_triangles(self):
        #f = open(self._filename)
        with open(self._filename) as f:
            #try:
            self._log.debug(u"Opened file '%s' as OFF file." % self._filename)
            vertices = []
            triangles = TriangleList()
            first_line = f.readline()
            if first_line.startswith("OFF"):
                vertice_count, polygon_count, edge_count = [
                    int(value.strip()) for value in f.readline().split(" ")
                ]
                for vertex_index in range(vertice_count):
                    vertices.append(
                        array([
                            float(coord.strip())
                            for coord in f.readline().split(" ")
                            if coord.strip() != ""
                        ]))
                for polygon_index in range(polygon_count):
                    n, v1, v2, v3 = [
                        int(value.strip()) for value in f.readline().split(" ")
                        if value.strip() != ""
                    ]
                    if n != 3:
                        raise FileFormatException(
                            "The file '%s' contains polygons, that are not triangles."
                            % self._filename)
                    triangles.append(
                        Triangle([vertices[v1], vertices[v2], vertices[v3]]))
            else:
                raise FileFormatException(
                    "The file '%s' is not of the expected format: %s" %
                    (self._filename, first_line))
        #finally:
        #    f.close()

        self._log.debug(u"Read %d triangles from file '%s'." %
                        (len(triangles), self._filename))
        return triangles
Example #6
0
from geometry import Triangle, Circle, Point, Square

if __name__ == '__main__':
    figure_list = [
        Triangle(Point(0, 0), Point(0, 2), Point(3, 4)),
        Circle(2, Point(0, 0)),
        Square(Point(0, 0), Point(2, 2))
    ]

    for figure in figure_list:
        figure.figure_square()
        figure.figure_perimeter()
        print(f'{figure.square},{figure.perimeter}')
Example #7
0
def main():
    """Calculate Delaunay triangulation and output an image"""
    # Anti-aliasing amount -- multiply screen dimensions by this when supersampling
    aa_amount = 4
    # Some gradients
    gradient = {
        'sunshine': Gradient(Color(255, 248, 9), Color(255, 65, 9)),
        'purples': Gradient(Color(255, 9, 204), Color(4, 137, 232)),
        'grass': Gradient(Color(255, 232, 38), Color(88, 255, 38)),
        'valentine': Gradient(Color(102, 0, 85), Color(255, 25, 216)),
        'sky': Gradient(Color(0, 177, 255), Color(9, 74, 102)),
        'ubuntu': Gradient(Color(119, 41, 83), Color(221, 72, 20)),
        'fedora': Gradient(Color(41, 65, 114), Color(60, 110, 180)),
        'debian': Gradient(Color(215, 10, 83), Color(10, 10, 10)),
        'opensuse': Gradient(Color(151, 208, 5), Color(34, 120, 8))
    }

    # Get command line arguments
    parser = argparse.ArgumentParser()
    parser.set_defaults(output_filename='triangles.png')
    parser.set_defaults(n_points=100)
    parser.set_defaults(distribution='uniform')

    # Value options
    parser.add_argument(
        '-o',
        '--output',
        dest='output_filename',
        help=
        'The filename to write the image to. Supported filetypes are BMP, TGA, PNG, and JPEG'
    )
    parser.add_argument(
        '-n',
        '--npoints',
        dest='n_points',
        type=int,
        help='The number of points to use when generating the triangulation.')
    parser.add_argument('-x',
                        '--width',
                        dest='width',
                        type=int,
                        help='The width of the image.')
    parser.add_argument('-y',
                        '--height',
                        dest='height',
                        type=int,
                        help='The height of the image.')
    parser.add_argument('-g',
                        '--gradient',
                        dest='gradient',
                        help='The name of the gradient to use.')
    parser.add_argument(
        '-i',
        '--image-file',
        dest='input_filename',
        help=
        'An image file to use when calculating triangle colors. Image dimensions will override dimensions set by -x and -y.'
    )
    parser.add_argument(
        '-k',
        '--darken',
        dest='darken_amount',
        type=int,
        help=
        'Darken random triangles my the given amount to make the pattern stand out more'
    )

    # Flags
    parser.add_argument(
        '-a',
        '--antialias',
        dest='antialias',
        action='store_true',
        help=
        'If enabled, draw the image at 4x resolution and downsample to reduce aliasing.'
    )
    parser.add_argument(
        '-l',
        '--lines',
        dest='lines',
        action='store_true',
        help='If enabled, draw lines along the triangle edges.')
    parser.add_argument(
        '--linethickness',
        dest='line_thickness',
        type=int,
        help='The thickness (in px) of edges drawn on the graph. Implies -l.')
    parser.add_argument(
        '--linecolor',
        dest='line_color',
        type=str,
        help=
        'The color of edges drawn on the graph in hex (e.g. ffffff for white). Implies -l.'
    )
    parser.add_argument(
        '-p',
        '--points',
        dest='points',
        action='store_true',
        help='If enabled, draw a circle for each vertex on the graph.')
    parser.add_argument(
        '--vertexradius',
        dest='vert_radius',
        type=int,
        help=
        'The radius (in px) of the vertices drawn on the graph. Implies -p.')
    parser.add_argument(
        '--vertexcolor',
        dest='vert_color',
        type=str,
        help=
        'The color of vertices drawn on the graph in hex (e.g. ffffff for white). Implies -p.'
    )
    parser.add_argument(
        '--distribution',
        dest='distribution',
        type=str,
        help=
        'The desired distribution of the random points. Options are uniform (default) or Halton.'
    )
    parser.add_argument(
        '-d',
        '--decluster',
        dest='decluster',
        action='store_true',
        help=
        'If enabled, try to avoid generating clusters of points in the triangulation. This will significantly slow down point generation.'
    )
    parser.add_argument(
        '-r',
        '--right',
        dest='right_tris',
        action='store_true',
        help='If enabled, generate right triangles rather than random ones.')
    parser.add_argument(
        '-e',
        '--equilateral',
        dest='equilateral_tris',
        action='store_true',
        help=
        'If enabled, generate equilateral triangles rather than random ones.')

    # Parse the arguments
    options = parser.parse_args()

    # Set the number of points to use
    npoints = options.n_points

    # Make sure the gradient name exists (if applicable)
    gname = options.gradient
    if not gname and not options.input_filename:
        print(
            'Require either gradient (-g) or input image (-i). Try --help for details.'
        )
        sys.exit(64)
    elif gname not in gradient and not options.input_filename:
        print('Invalid gradient name')
        sys.exit(64)
    elif options.input_filename:
        # Warn if a gradient was selected as well as an image
        if options.gradient:
            print('Image supercedes gradient; gradient selection ignored')
        background_image = Image.open(options.input_filename)

    # Input and output files can't be the same
    if options.input_filename == options.output_filename:
        print('Input and output files must be different.')
        sys.exit(64)

    # If an image is being used as the background, set the canvas size to match it
    if options.input_filename:
        # Warn if overriding user-defined width and height
        if options.width or options.height:
            print('Image dimensions supercede specified width and height')
        size = background_image.size
    else:
        # Make sure width and height are positive
        if options.width <= 0 or options.height <= 0:
            print('Width and height must be greater than zero.')
            sys.exit(64)

        size = (options.width, options.height)

    # Generate points on this portion of the canvas
    scale = 1.25
    if options.equilateral_tris:
        points = generate_equilateral_points(npoints, size)
    elif options.right_tris:
        points = generate_rectangular_points(npoints, size)
    else:
        if options.distribution == 'uniform':
            points = generate_random_points(npoints, size, scale,
                                            options.decluster)
        elif options.distribution == 'halton':
            points = generate_halton_points(npoints, size)
        else:
            print('Unrecognized distribution type.')
            sys.exit(64)

    # Dedup the points
    points = list(set(points))

    # Calculate the triangulation
    triangulation = delaunay_triangulation(points)

    # Failed to find a triangulation
    if not triangulation:
        print('Failed to find a triangulation.')
        sys.exit(1)

    # Translate the points to screen coordinates
    trans_triangulation = list(
        map(lambda x: cart_to_screen(x, size), triangulation))

    # Assign colors to the triangles
    if options.input_filename:
        colors = color_from_image(background_image, trans_triangulation)
    else:
        colors = color_from_gradient(gradient[gname], size,
                                     trans_triangulation)

    # Darken random triangles
    if options.darken_amount:
        for i in range(0, len(colors)):
            c = colors[i]
            d = randrange(options.darken_amount)
            darkened = Color(max(c.r - d, 0), max(c.g - d, 0), max(c.b - d, 0))
            colors[i] = darkened

    # Set up for anti-aliasing
    if options.antialias:
        # Scale the image dimensions
        size = (size[0] * aa_amount, size[1] * aa_amount)
        # Scale the graph
        trans_triangulation = [
            Triangle(Point(t.a.x * aa_amount, t.a.y * aa_amount),
                     Point(t.b.x * aa_amount, t.b.y * aa_amount),
                     Point(t.c.x * aa_amount, t.c.y * aa_amount))
            for t in trans_triangulation
        ]

    # Create image object
    image = Image.new('RGB', size, 'white')
    # Get a draw object
    draw = ImageDraw.Draw(image)
    # Draw the triangulation
    draw_polys(draw, colors, trans_triangulation)

    if options.lines or options.line_thickness or options.line_color:
        if options.line_color is None:
            line_color = Color(255, 255, 255)
        else:
            line_color = hex_to_color(options.line_color)

        draw_lines(draw, line_color, trans_triangulation,
                   options.line_thickness)

    if options.points or options.vert_radius or options.vert_color:
        if options.vert_color is None:
            vertex_color = Color(255, 255, 255)
        else:
            vertex_color = hex_to_color(options.vert_color)

        draw_points(draw, vertex_color, trans_triangulation,
                    options.vert_radius)

    # Resample the image using the built-in Lanczos filter
    if options.antialias:
        size = (int(size[0] / aa_amount), int(size[1] / aa_amount))
        image = image.resize(size, Image.ANTIALIAS)

    # Write the image to a file
    image.save(options.output_filename)
    print('Image saved to %s' % options.output_filename)
    sys.exit(0)
Example #8
0
File: Q_A.py Project: WOKNz/HW3
        for line in stringlines:
            # split the line by comma
            fields = line.split(",")
            points.append(
                Point(float(fields[1]), float(fields[2]),
                      float(fields[3].replace('\n', '')), int(fields[0])))

    # Reading triangles
    with open('triangulation.txt', "r", encoding="utf8") as stringlines:
        next(stringlines)
        for line in stringlines:
            # split the line by comma
            fields = line.split(",")
            triangles.append(
                Triangle(points[int(fields[1]) - 1],
                         points[int(fields[2]) - 1],
                         points[int(fields[3].replace('\n', '')) - 1],
                         int(fields[0])))
    plt.axes().set_aspect('equal')
    # Plotting both points and triangles (with duplicates)
    for i in range(0, len(points)):
        plt.plot(points[i].x, points[i].y, 'bo--')
    for i in range(0, len(triangles)):
        plt.plot([
            triangles[i].p1.x, triangles[i].p2.x, triangles[i].p3.x,
            triangles[i].p1.x
        ], [
            triangles[i].p1.y, triangles[i].p2.y, triangles[i].p3.y,
            triangles[i].p1.y
        ], 'b')
    # plt.show()
    axes = plt.axis()  # Saving ratio of plot axes
Example #9
0
File: luz.py Project: grosa/luz
    def __init__(self, filename="scene.json"):

        self.lights = []
        self.objects = []

        # read in the json
        with open(filename, "r") as json_file:
            scene = json.load(json_file)

        for light in scene['scene']['lights']:
            l = Light(origin=light['origin'],
                      radius=light['radius'],
                      brightness=light['brightness'],
                      color=light['color'])
            self.lights.append(l)
            self.objects.append(l)

        for object in scene['scene']['objects']:

            texture = None
            scale = 1.0

            if 'texture' in object:
                texture = object['texture']

            if 'scale' in object:
                scale = object['scale']

            if (object['shape'] == "Sphere"):

                self.objects.append(
                    Sphere(origin=object['origin'],
                           radius=object['radius'],
                           diffuse=object['diffuse'],
                           reflection=object['reflection'],
                           shiny=object['shiny'],
                           k=object['k'],
                           refraction=object['refraction'],
                           index=object['index'],
                           color=object['color'],
                           texture=texture,
                           uv=object['uv']))
            elif (object['shape'] == "Skybox"):

                self.objects.append(
                    Skybox(origin=object['origin'],
                           radius=object['radius'],
                           diffuse=object['diffuse'],
                           reflection=object['reflection'],
                           shiny=object['shiny'],
                           k=object['k'],
                           refraction=object['refraction'],
                           index=object['index'],
                           color=object['color'],
                           texture=texture,
                           uv=object['uv']))

            elif (object['shape'] == "Plane"):

                self.objects.append(
                    Plane.Plane(origin=object['origin'],
                                normal=object['normal'],
                                diffuse=object['diffuse'],
                                reflection=object['reflection'],
                                refraction=object['refraction'],
                                index=object['index'],
                                shiny=object['shiny'],
                                k=object['k'],
                                color=object['color'],
                                texture=texture,
                                scale=scale))
            elif (object['shape'] == "Triangle"):
                self.objects.append(
                    Triangle.Triangle(v0=object['v0'],
                                      v1=object['v1'],
                                      v2=object['v2'],
                                      diffuse=object['diffuse'],
                                      reflection=object['reflection'],
                                      refraction=object['refraction'],
                                      index=object['index'],
                                      shiny=object['shiny'],
                                      k=object['k'],
                                      color0=object['color0'],
                                      color1=object['color1'],
                                      color2=object['color2']))

        camera = scene['scene']['camera']
        self.camera = Camera(origin=camera['origin'],
                             target=camera['target'],
                             length=camera['length'],
                             aperture=camera['aperture'],
                             samples=camera['samples'])

        self.ambient = np.array(scene['scene']['ambient'])
        self.background = np.array(scene['scene']['background'])
Example #10
0
        if darken_amount:
            for i in range(0, len(colors)):
                c = colors[i]
                d = randrange(darken_amount)
                darkened = Color(max(c.r - d, 0), max(c.g - d, 0),
                                 max(c.b - d, 0))
                colors[i] = darkened

        # Set up for anti-aliasing
        if antialias:
            # Scale the image dimensions
            size = (size[0] * aa_amount, size[1] * aa_amount)
            # Scale the graph
            trans_triangulation = [
                Triangle(Point(t.a.x * aa_amount, t.a.y * aa_amount),
                         Point(t.b.x * aa_amount, t.b.y * aa_amount),
                         Point(t.c.x * aa_amount, t.c.y * aa_amount))
                for t in trans_triangulation
            ]

        # Create image object
        image = Image.new('RGB', size, 'white')
        # Get a draw object
        draw = ImageDraw.Draw(image)
        # Draw the triangulation
        draw_polys(draw, colors, trans_triangulation)

        if lines or line_thickness or line_color:
            if line_color is None:
                line_color = Color(255, 255, 255)
            else:
Example #11
0
@author: Gosha
'''

from geometry import Point, Camera, Direction, Triangle
from objects import DPoint, DCamera, DSurface
from screen import Screen

if(__name__ == '__main__'):
    cam = Camera(Point((0, 0, 0)), Direction((0, 0, 0)))
    dCam = DCamera(cam)
    screen = Screen()
    screen.linkCamera(dCam)

    sides = []

    sides.append(DSurface([Triangle(Point((-10, 10, 10)), Point((10, 10, 10)), Point((10, 10, -10))),
                           Triangle(Point((-10, 10, 10)), Point((-10, 10, -10)), Point((10, 10, -10)))], (1, 1, 0), (0, 0, 0)))
    sides.append(DSurface([Triangle(Point((-10, -10, 10)), Point((10, -10, 10)), Point((10, -10, -10))),
                           Triangle(Point((-10, -10, 10)), Point((-10, -10, -10)), Point((10, -10, -10)))], (0.5, 0.5, 0.5), (0, 0, 0)))
    sides.append(DSurface([Triangle(Point((10, -10, 10)), Point((10, 10, 10)), Point((10, 10, -10))),
                           Triangle(Point((10, -10, 10)), Point((10, -10, -10)), Point((10, 10, -10)))], (0, 1, 0), (0, 0, 0)))
    for side in sides:
        dCam.show(side)

    for x in [-10, 10]:
        for y in [-10, 10]:
            for z in [-10, 10]:
                dCam.show(DPoint(Point((x, y, z))))

    screen.updateLoop()