Esempio n. 1
0
def triangulate_earclip(vertex_chain):
    if not isinstance(vertex_chain, list):
        if isinstance(vertex_chain, tuple):
            vertex_chain = list(vertex_chain)
        else:
            raise GraphicsError(
                "\n\nGraphicsError: input argument for triangulation must be a list or tuple,"
                f" not {vertex_chain}")
    if len(vertex_chain) == 3:
        return [tuple(vertex_chain)]
    elif len(vertex_chain) < 3:
        raise GraphicsError(
            "\n\nGraphicsError: polygon for triangulation must have at least 3 vertices, currently, "
            f"only {len(vertex_chain)} vertices are present")

    vertex_chain = vertex_chain.copy()

    if is_clockwise(vertex_chain):
        vertex_chain.reverse()

    triangles = []
    size = len(vertex_chain)
    while size > 3:
        for i, point in enumerate(vertex_chain):
            p1 = vertex_chain[i - 1]
            p3 = vertex_chain[(i + 1) % size]
            if not is_reflex(p1, point, p3):
                if contains_no_other_points(p1, point, p3, vertex_chain):
                    vertex_chain.remove(point)
                    size -= 1
                    triangles.append((p1, point, p3))

    triangles.append(tuple(vertex_chain))
    return triangles
Esempio n. 2
0
 def slope(self, p2):
     if not isinstance(p2, Point):
         raise GraphicsError(
             f"\n\np2 argument for slope calculation must be a Point class, not {p2}"
         )
     if self.x == p2.x:
         raise GraphicsError(
             f"\n\nThe two points have the same x value, cannot calculate slope!"
         )
     return (self.y - p2.y) / (self.x - p2.x)
Esempio n. 3
0
    def __init__(self, p, start_angle, end_angle, radius, radius2=None, outline=None, outline_width=None,
                 cursor="arrow", arrow=None, resolution=10, smooth=True, bounds_width=10, layer=0, tag=None):

        if not isinstance(p, list):
            raise GraphicsError(f"\n\nGraphicsError: anchor for arc (p) must be a list in the form [x, y], not {p}")
        
        if not (isinstance(start_angle, int) or isinstance(start_angle, float)):
            raise GraphicsError(f"\n\nGraphicsError: start_angle must be an integer or float, not {start_angle}")
        if not (isinstance(end_angle, int) or isinstance(end_angle, float)):
            raise GraphicsError(f"\n\nGraphicsError: end_angle must be an integer or float, not {end_angle}")
        
        if not (isinstance(radius, int) or isinstance(radius, float)):
            raise GraphicsError(f"\n\nGraphicsError: Arc radius must be an integer or float, not {radius}")
        if radius2 is not None:
            if not (isinstance(radius2, int) or isinstance(radius2, float)):
                raise GraphicsError(f"\n\nGraphicsError: Arc radius2 must be an integer or float, not {radius2}")
        
        self.start_angle = start_angle
        self.end_angle = end_angle

        self.anchor = p

        self.radius1 = radius
        if radius2 is None:
            self.radius2 = radius
        else:
            self.radius2 = radius

        angle_change = (end_angle - start_angle) / resolution

        range_end = 90 / angle_change
        decimal_points = min([len(str(range_end).split('.')[1]), 3])

        x_coeff = sum([abs(math.cos(math.radians(i * angle_change + start_angle)))
                       for i in range(int(range_end * 10 ** decimal_points))])
        y_coeff = sum([abs(math.sin(math.radians(i * angle_change + start_angle)))
                       for i in range(int(range_end * 10 ** decimal_points))])

        x_coeff /= 10 ** decimal_points
        y_coeff /= 10 ** decimal_points

        angle_change = (end_angle - start_angle) / resolution

        x_change = self.radius1 / 2 / x_coeff
        y_change = self.radius2 / 2 / y_coeff

        self.points = [[p[0] - x_change/2, p[1] - self.radius2 / 2]]

        for i in range(resolution):
            cur_angle = (i * angle_change) + start_angle
            self.points.append([self.points[-1][0] + x_change * math.cos(math.radians(cur_angle)), self.points[-1][1] + y_change * math.sin(math.radians(cur_angle))])

        CurvedLine.__init__(self, *self.points, outline=outline, outline_width=outline_width, arrow=arrow,
                            resolution=0, interpolation="spline", smooth=smooth, bounds_width=bounds_width, layer=layer,
                            tag=tag)
Esempio n. 4
0
def triangulate_chazelle(vertex_chain):
    if not isinstance(vertex_chain, list):
        if isinstance(vertex_chain, tuple):
            vertex_chain = list(vertex_chain)
        else:
            raise GraphicsError(
                "\n\nGraphicsError: input argument for triangulation must be a list or tuple,"
                f" not {vertex_chain}")
    if len(vertex_chain) == 3:
        return [tuple(vertex_chain)]
    elif len(vertex_chain) < 3:
        raise GraphicsError(
            "\n\nGraphicsError: polygon for triangulation must have at least 3 vertices, currently, "
            f"only {len(vertex_chain)} vertices are present")
Esempio n. 5
0
def create_square_wave(filename,
                       duration,
                       freq,
                       tag=None,
                       volume=1,
                       sample_rate=7000):

    if not (isinstance(duration, float) or isinstance(duration, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: duration value for square wave must be an int or float, not {duration}"
        )
    if not (isinstance(volume, float) or isinstance(volume, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for square wave must be a float or int, not {volume}"
        )
    if not (0 <= volume <= 1):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for square wave must be between 0 & 1, not {volume}"
        )

    if not (isinstance(sample_rate, float) or isinstance(sample_rate, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: sample rate for square wave must be an integer or float,"
            f" not {sample_rate}")

    audio = [0]
    num_samples = duration * sample_rate

    volume *= 127.5

    i = 0
    f = 0

    check = sample_rate / (freq * 0.5)
    for _ in range(num_samples):
        if f > check:
            i = 1 - i
            f = 0
            audio.append(volume * i)
        else:
            f += 1
            audio.append(audio[-1])
    audio.pop()

    return create_sound_from_values(filename,
                                    audio,
                                    tag=tag,
                                    channels=1,
                                    sample_rate=sample_rate)
Esempio n. 6
0
 def bind_frame_to(self, obj):
     if not isinstance(obj, AnimatedImage):
         if obj in GraphicsObject.tagged_objects:
             obj = GraphicsObject.tagged_objects[obj]
             if not isinstance(obj, AnimatedImage):
                 raise GraphicsError(
                     "\n\nGraphicsError: object to bind frame to must be an Animated Image object, "
                     f"not {obj}")
         else:
             raise GraphicsError(
                 "\n\nGraphicsError: object to bind frame to must be an Animated Image object, "
                 f"not {obj}")
     obj.frame_bound_objects.add(self)
     self.set_autoflush(False)
     return self
Esempio n. 7
0
 def set_frame_increment_callback(self, func):
     if not (callable(func) or func is None):
         raise GraphicsError(
             "\n\nGraphicsError: Frame Increment callback for Animated Image must be a function, "
             f"not {func}")
     self.callbacks["frame increment"] = func
     return self
Esempio n. 8
0
def combination(n, k):
    if isinstance(n, int):
        if isinstance(k, int):
            if n + 1 > k:  # faster than n >= k
                return goopylib.math.CBezierCurve.combination(n, k)
            else:
                raise GraphicsError(
                    f"\n\nGraphicsError: n must be >= k, not n={n} & k={k}")
        else:
            raise GraphicsError(
                f"\n\nGraphicsError: k argument for combination must be an integer, not {k}"
            )
    else:
        raise GraphicsError(
            f"\n\nGraphicsError: n argument for combination must be an integer, not {n}"
        )
Esempio n. 9
0
def bezier_curve(t, control_points):
    if isinstance(t, (float, int)):
        return goopylib.math.CBezierCurve.bezier_curve(t, control_points)
    else:
        raise GraphicsError(
            f"\n\nGraphicsError: t parameter for bezier curve must be a float or int, not {t}"
        )
Esempio n. 10
0
 def move_y(self, dy):
     if not (isinstance(dy, int) or isinstance(dy, float)):
         raise GraphicsError(
             "\n\nThe value to move the point by (dy) must be a number (integer or float), "
             f"not {dy}")
     self.y += dy
     return self
Esempio n. 11
0
 def move_to_y(self, y):
     if not (isinstance(y, int) or isinstance(y, float)):
         raise GraphicsError(
             f"\n\nThe value to move the point by (y) must be a number (integer or float), not {y}"
         )
     self.y = y
     return self
Esempio n. 12
0
def CosineCurve(t, control_points):
    if not len(control_points) > 2:
        raise GraphicsError("Length of Control Points must be greater than 2")

    total_distance = control_points[-1].x - control_points[0].x
    time_x = t * total_distance + control_points[0].x

    for i, point in enumerate(control_points):
        if time_x < point.x:
            lower_point = i - 1
            break

    upper_point = lower_point + 1
    points_distance = control_points[lower_point].distance_x(
        control_points[upper_point])

    x = (1 -
         t) * control_points[lower_point].x + t * control_points[upper_point].x
    proportion_done = (time_x -
                       control_points[lower_point].x) / points_distance

    ft = t * math.pi
    f = (1 - math.cos(ft)) / 2

    return Point(x, lower_point * (1 - f) + upper_point * f)
Esempio n. 13
0
 def get_text(self):
     if self.drawn and self.graphwin.is_open():
         return self.widget.get("1.0", "end-1c")
     else:
         raise GraphicsError(
             "\n\nGraphicsError: get_text() function for the Multiline Entry object can only be "
             "used if the object is drawn and the window is open")
Esempio n. 14
0
 def move_to_x(self, x):
     if not (isinstance(x, int) or isinstance(x, float)):
         raise GraphicsError(
             f"\n\nThe value to move the point by (x) must be a number (integer or float), not {x}"
         )
     self.x = x
     return self
Esempio n. 15
0
 def move_x(self, dx):
     if not (isinstance(dx, int) or isinstance(dx, float)):
         raise GraphicsError(
             "\n\nThe value to move the point by (dx) must be a number (integer or float), "
             f"not {dx}")
     self.x += dx
     return self
Esempio n. 16
0
def set_style(style="default"):
    global global_style

    if style not in STYLES.keys():
        raise GraphicsError(
            f"The style specified ({style}) does not exist, must be one of {list(STYLES.keys())}"
        )
    global_style = style
Esempio n. 17
0
def rational_bezier_curve(t, control_points, weights):
    if isinstance(t, (float, int)):
        return goopylib.math.CBezierCurve.rational_bezier_curve(
            t, control_points, weights)
    else:
        raise GraphicsError(
            "\n\nGraphicsError: t parameter for rational bezier curve must be a float or int, "
            f"not {t}")
Esempio n. 18
0
    def __init__(self,
                 *checkboxes,
                 state=0,
                 cursor="arrow",
                 layer=0,
                 tag=None,
                 autoflush=True):
        if len(checkboxes) > 0:
            for obj in checkboxes:
                if not isinstance(obj, Checkbox):
                    raise GraphicsError(
                        f"\n\nGraphicsError: All Radio Button states must be Checkboxes, not {obj}"
                    )
                if obj in GraphicsObject.cyclebutton_instances:
                    GraphicsObject.cyclebutton_instances.remove(obj)
                obj.set_state(False)

            self.checkboxes = checkboxes

            super().__init__(options=(), cursor=cursor, layer=layer, tag=tag)
            if autoflush:
                GraphicsObject.radiobutton_instances.add(self)

            self.state = state

            number_of_states = 0
            self.anchor = [0, 0]
            for state in self.checkboxes:
                state_anchor = state.get_anchor()
                if state_anchor is not None:
                    self.anchor[0] += state_anchor[0]
                    self.anchor[1] += state_anchor[1]
                    number_of_states += 1

            if number_of_states != 0:
                self.anchor = [
                    self.anchor[0] // number_of_states,
                    self.anchor[1] // number_of_states
                ]

            self.current_state = self.checkboxes[self.state].set_state(True)
        else:
            raise GraphicsError(
                "\n\nGraphicsError: RadioButton must have at least 1 state, not 0"
            )
Esempio n. 19
0
def create_sawtooth_wave(filename,
                         duration,
                         freq,
                         reverse=False,
                         tag=None,
                         volume=1,
                         sample_rate=7000):

    if not (isinstance(duration, float) or isinstance(duration, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: duration value for sawtooth wave must be an int or float, not {duration}"
        )
    if not (isinstance(volume, float) or isinstance(volume, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for sawtooth wave must be a float or int, not {volume}"
        )
    if not (0 <= volume <= 1):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for sawtooth wave must be between 0 & 1, not {volume}"
        )

    if not (isinstance(sample_rate, float) or isinstance(sample_rate, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: sample rate for sawtooth wave must be an integer or float,"
            f" not {sample_rate}")

    audio = []
    num_samples = int(duration * sample_rate)

    scale = freq / sample_rate
    volume *= 127.5
    for x in range(num_samples):
        x *= scale
        audio.append(
            volume * (x - int(x))
        )  # The int function is equivalent to the floor function for positive numbers

    if reverse:
        audio.reverse()

    return create_sound_from_values(filename,
                                    audio,
                                    tag=tag,
                                    channels=1,
                                    sample_rate=sample_rate)
Esempio n. 20
0
    def __init__(self,
                 center,
                 radius1,
                 radius2,
                 bounds=None,
                 fill=None,
                 outline=None,
                 outline_width=None,
                 cursor="arrow",
                 layer=0,
                 tag=None):

        if not isinstance(center, list):
            raise GraphicsError(
                "\n\nGraphicsError: center argument for Oval must be a list in the form [x, y], "
                f"not {center}")

        if not isinstance(radius1, int):
            raise GraphicsError(
                f"\n\nGraphicsError: radius1 argument for Oval must be an integer, not {radius1}"
            )
        if not isinstance(radius2, int):
            raise GraphicsError(
                f"\n\nGraphicsError: radius2 argument for Oval must be an integer, not {radius2}"
            )

        p1 = [center[0] - radius1, center[1] - radius2]
        p2 = [center[0] + radius1, center[1] + radius2]

        self.radius1 = radius1
        self.radius2 = radius2

        self.center = center

        gpBBox.BBox.__init__(self,
                             p1,
                             p2,
                             bounds=bounds,
                             fill=fill,
                             outline=outline,
                             outline_width=outline_width,
                             cursor=cursor,
                             layer=layer,
                             tag=tag)
Esempio n. 21
0
def LinearInterpolation(p0, p1, t):
    if not isinstance(p0, Point):
        raise GraphicsError(
            f"\n\nGraphicsError: p0 Point to Interpolate between must be a Point object, not {p0}"
        )
    if not isinstance(p1, Point):
        raise GraphicsError(
            f"\n\nGraphicsError: p1 Point to Interpolate between must be a Point object, not {p1}"
        )
    if not (isinstance(t, int) or isinstance(t, float)):
        raise GraphicsError(
            f"\n\nGraphicsError: t parameter for interpolation must be an int or float, not {t}"
        )
    if not 0 <= t <= 1:
        raise GraphicsError(
            f"\n\nGraphicsError: t parameter must be between 0 & 1, 0 <= t <= 1, not {t}"
        )

    return (1 - t) * p0.y + t * p1.y
Esempio n. 22
0
def create_sin_wave(filename,
                    duration,
                    freq,
                    tag=None,
                    volume=1,
                    sample_rate=7000):

    if not (isinstance(duration, float) or isinstance(duration, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: duration value for sin wave must be an int or float, not {duration}"
        )
    if not (isinstance(freq, int) or isinstance(freq, float)):
        raise GraphicsError(
            f"\n\nGraphicsError: freq value for sin wave must be an int or float, not {freq}"
        )

    if not (isinstance(volume, float) or isinstance(volume, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for sin wave must be a float or int, not {volume}"
        )
    if not (0 <= volume <= 1):
        raise GraphicsError(
            f"\n\nGraphicsError: volume for sin wave must be between 0 & 1, not {volume}"
        )

    if not (isinstance(sample_rate, float) or isinstance(sample_rate, int)):
        raise GraphicsError(
            f"\n\nGraphicsError: sample rate for sin wave must be an integer or float,"
            f" not {sample_rate}")

    audio = []
    num_samples = int(duration * sample_rate)

    scale = 6.283 * (freq / sample_rate)
    volume *= 127.5
    for x in range(num_samples):
        audio.append(volume * mathsin(x * scale))

    return create_sound_from_values(filename,
                                    audio,
                                    tag=tag,
                                    channels=1,
                                    sample_rate=sample_rate)
Esempio n. 23
0
    def __init__(self,
                 p1,
                 p2,
                 bounds=None,
                 fill=None,
                 outline=None,
                 outline_width=None,
                 layer=0,
                 cursor="arrow",
                 is_rounded=False,
                 roundness=5,
                 tag=None):

        # This makes sure that the p1 & p2 arguments of the Rectangle are lists, raises an error otherwise
        if not isinstance(p1, list):
            raise GraphicsError(
                "\n\nGraphicsError: p1 argument for Rectangle must be a list in the form [x, y], "
                f"not {p1}")
        if not isinstance(p2, list):
            raise GraphicsError(
                "\n\nGraphicsError: p2 argument for Rectangle must be a list in the form [x, y], "
                f"not {p2}")

        # Makes sure that the roundness argument is an integer, raises an error otherwise
        if not isinstance(roundness, int):
            raise GraphicsError(
                "\n\nGraphicsError: roundness argument for Rectangle must be an integer, "
                f"not {roundness}")

        # A call to the super class to initialize important variables of the Rectangle class.
        gpBBox.BBox.__init__(self,
                             p1,
                             p2,
                             bounds=bounds,
                             fill=fill,
                             outline=outline,
                             outline_width=outline_width,
                             cursor=cursor,
                             layer=layer,
                             tag=tag)

        self.is_rounded = is_rounded  # A variable defining whether the rectangle is rounded
        self.sharpness = roundness  # Usually values between 2 & 10 work well.
Esempio n. 24
0
 def set_value(self, value):
     if value < self.minimum or value > self.maximum:
         raise GraphicsError(
             f"\n\nValue to set the Slider Bar must be within {self.minimum} and {self.maximum} not {value}"
         )
     self.state = value
     try:
         self.redraw()
     except AttributeError:
         self.reload()
Esempio n. 25
0
    def __init__(self, x, y):

        if not ((isinstance(x, int) or isinstance(x, float)) and
                (isinstance(y, int) or isinstance(y, float))):
            raise GraphicsError(
                "\n\nx (x={}) & y (y={}) positions must be integers".format(
                    x, y))

        self.x = x
        self.y = y
Esempio n. 26
0
    def move_up_layer(self, layers=1):
        if not isinstance(layers, int):
            raise GraphicsError(
                f"\n\nGraphicsError: layers to move up must be an integer, not {layers}"
            )
        if layers < 0:
            raise GraphicsError(
                "\n\nGraphicsError: layers to move up must be greater than (or equal to) 0, "
                f"not {layers}")

        GraphicsObject.object_layers[self.layer].remove(self)
        self.layer += layers

        while self.layer > len(GraphicsObject.object_layers) - 1:
            GraphicsObject.object_layers.append([])
        GraphicsObject.object_layers[self.layer].add(self)

        for obj in self.imgs:
            obj.move_up_layer(layers=layers)
        return self
Esempio n. 27
0
    def bind_state_to(self, other):
        if not isinstance(other, Checkbox):
            raise GraphicsError(
                f"Object to bind this Checkbox to must be another Checkbox, not {other}"
            )
        other.bound_objects.add(self)

        self.autoflush = False
        self.set_state(other.state)

        return self
Esempio n. 28
0
    def set_layer(self, layer=0):
        if not isinstance(layer, int):
            raise GraphicsError(
                f"\n\nGraphicsError: layer to set to must be an integer, not {layer}"
            )
        if layer < 0:
            raise GraphicsError(
                "\n\nGraphicsError: layer to set to must be greater than (or equal to) 0, "
                f"not {layer}")

        for obj in self.imgs:
            obj.set_layer(layer=layer)

        GraphicsObject.object_layers[self.layer].remove(self)
        while layer > len(GraphicsObject.object_layers) - 1:
            GraphicsObject.object_layers.append({*()})
        GraphicsObject.object_layers[layer].add(self)

        self.layer = layer

        return self
Esempio n. 29
0
def windows_command(command):
    buf = c_buffer(255)
    command = command.encode(getfilesystemencoding())

    error_code = windll.winmm.mciSendStringA(command, buf, 254, 0)

    if error_code:
        error_buffer = c_buffer(255)
        windll.winmm.mciGetErrorStringA(error_code, error_buffer, 254)
        raise GraphicsError(
            f'\n\tError {error_code} for command: \n\t\t{command.decode()}\n\t{error_buffer.value.decode()}'
        )
    return buf.value
Esempio n. 30
0
def HermiteInterpolation(p0, p1, p2, p3, t, tension, bias):
    for i, p in enumerate([p0, p1, p2, p3]):
        if not isinstance(p, Point):
            raise GraphicsError(
                f"\n\nGraphicsError: p{i} Point to Interpolate between must be a Point object, not {p}"
            )

    if not (isinstance(t, int) or isinstance(t, float)):
        raise GraphicsError(
            f"\n\nGraphicsError: t parameter for interpolation must be an int or float, not {t}"
        )
    if not 0 <= t <= 1:
        raise GraphicsError(
            f"\n\nGraphicsError: t parameter must be between 0 & 1, 0 <= t <= 1, not {t}"
        )

    if not (isinstance(tension, int) or isinstance(tension, float)):
        raise GraphicsError(
            f"\n\nGraphicsError: tension for interpolation must be an int or float, not {tension}"
        )
    if not (isinstance(bias, int) or isinstance(bias, float)):
        raise GraphicsError(
            f"\n\nGraphicsError: bias for interpolation must be an int or float, not {bias}"
        )

    t2 = t**2
    t3 = t**3

    m0 = (p1.y - p0.y) * (1 + bias) * (1 - tension) / 2
    m0 += (p2.y - p1.y) * (1 - bias) * (1 - tension) / 2
    m1 = (p2.y - p1.y) * (1 + bias) * (1 - tension) / 2
    m1 += (p3.y - p2.y) * (1 - bias) * (1 - tension) / 2

    a0 = 2 * t3 - 3 * t2 + 1
    a1 = t3 - 2 * t2 + t
    a2 = t3 - t2
    a3 = -2 * t3 + 3 * t2

    return a0 * p1.y + a1 * m0 + a2 * m1 + a3 * p2.y