How to get the area of shape filled using turtle

2024/11/18 17:53:20

I graphed a fractal shape in Python using turtle, and am trying to get the area of this fractal after a sufficiently high iteration. This fractal is related to the Koch snowflake, for those interested.

I was able to fill in the fractal with black using begin_fill() and end_fill(). I then used this answer to get the color of each pixel in a valid range. If it wasn't equal to white, then I added one to the count. This solution works for a small iteration of the fractal. However, it takes an exorbitant amount of time when trying to go to a higher iteration.

Here is my code for the fractal.

def realSnowflake(length, n, s, show = False):#n: after n iterations#s: number of sides (in Koch snowflake, it is 3)#length: starting side lengthturtle.begin_fill()a = 360/sfor i in range(s):snowflake(length, n, s) turtle.right(a)turtle.end_fill()

Here is my code for finding the area.

count = 0
canvas = turtle.getcanvas()
for x in range(x1, x2+1): #limits calculated through mathfor y in range(y2, y1+1):if get_pixel_color(x, y, canvas) != "white":count += 1

I want to be able to find the area of this fractal faster. It takes the most amount of time not in graphing the fractal, but in the double for loop of x and y. I think if there is a way to find the area while turtle is filling, this would be optimal.

Answer

the complexity of the image drawn shouldn't affect the time it takesto count black pixels

Unfortunately, in this case it does. If we lookup an earlier source of the get_pixel_color() code, we find the telling text, "is slow". But it's worse than that, it actually slows down!

This code is built atop canvas.find_overlapping() which is looking for high level objects that sit over X,Y. In the case of tkinter filling an object for turtle, there is overlap, up to three layers in the code below. This increases as the factal gets more complex. Here's my code to demonstrate this:

from turtle import Screen, Turtle
from math import floor, ceil
from time import timedef koch_curve(turtle, iterations, length):if iterations == 0:turtle.forward(length)else:for angle in [60, -120, 60, 0]:koch_curve(turtle, iterations - 1, length / 3)turtle.left(angle)def koch_snowflake(turtle, iterations, length):turtle.begin_poly()turtle.begin_fill()for _ in range(3):koch_curve(turtle, iterations, length)turtle.right(120)turtle.end_fill()turtle.end_poly()return turtle.get_poly()def bounding_box(points):x_coordinates, y_coordinates = zip(*points)return [(min(x_coordinates), min(y_coordinates)), (max(x_coordinates), max(y_coordinates))]def get_pixel_color(x, y):ids = canvas.find_overlapping(x, y, x, y)  # This is our bottleneck!if ids: # if list is not emptyindex = ids[-1]return canvas.itemcget(index, 'fill')return 'white' # default colorscreen = Screen()
screen.setup(500, 500)
turtle = Turtle(visible=False)
turtle.color('red')canvas = screen.getcanvas()
width, height = screen.window_width(), screen.window_height()for iterations in range(1, 7):screen.clear()turtle.clear()screen.tracer(False)polygon_start_time = time()polygon = koch_snowflake(turtle, iterations, 200)polygon_elapsed = round((time() - polygon_start_time) * 1000)  # millisecondsscreen.tracer(True)((x_min, y_min), (x_max, y_max)) = bounding_box(polygon)screen.update()# Convert from turtle coordinates to tkinter coordinatesx1, y1 = floor(x_min), floor(-y_max)x2, y2 = ceil(x_max), ceil(-y_min)canvas.create_rectangle((x1, y1, x2, y2))count = 0pixel_count_start_time = time()for x in range(x1, x2 + 1):for y in range(y1, y2 + 1):if get_pixel_color(x, y) == 'red':count += 1pixel_count_elapsed = round((time() - pixel_count_start_time) * 1000)print(iterations, count, polygon_elapsed, pixel_count_elapsed, ((x1, y1), (x2, y2)))screen.exitonclick()

CONSOLE OUTPUT

> python3 test.py
1 23165 1 493 ((-1, -58), (201, 174))
2 26064 4 1058 ((-1, -58), (201, 174))
3 27358 9 1347 ((-1, -58), (201, 174))
4 28159 29 2262 ((0, -58), (201, 174))
5 28712 104 5925 ((0, -58), (201, 174))
6 28881 449 19759 ((0, -58), (200, 174))
> 

The fields are as follows:

  1. Iterations
  2. Pixels counted
  3. Time to draw image in ms
  4. Time to count pixels in ms
  5. Computed bounding box (in tkinter coordinates)

FINAL ITERATION SCREEN OUTPUT

enter image description here

Note that the fractal is drawn by turtle but the bounding box is drawn by the underlying tkinter to verify that we converted coordinates correctly.

POSSIBLE SOLUTION

Find an approach that doesn't rely on find_overlapping(). I think the next thing to investigate would be either to convert the canvas to a bitmap image, and pixel count it, or draw a bitmap image in the first place. There are several discusions on SO about converting a canvas to a bitmap, either directly or indirectly via Postscript. You could then load in that image and use one of the Python image libraries to count the pixels. Although more complicated, it should provide a constant time way of counting pixels. Alternately, there are libraries to draw bitmaps, which you could load into tkinter for visual verfication, but could then pixel count directly. Good luck!

https://en.xdnf.cn/q/118650.html

Related Q&A

What distinguishes a command from needing () vs not?

I recently spent way too long debugging a piece of code, only to realize that the issue was I did not include a () after a command. What is the logic behind which commands require a () and which do not…

python iterate yaml and filter result

I have this yaml file data:- name: acme_aws1source: awspath: acme/acme_aws1.zip- name: acme_gke1source: gkepath: acme/acme_gke1.zip- name: acme_ocisource: ocipath: acme/acme_oci1.zip- name: acme_aws2so…

Faster way to looping pixel by pixel to calculate entropy in an image

I have been calculating the entropy of an image with a pixel by pixel convolution operation, and it has been working but very slowly, increasing the execution time with the kernel size. Here is my func…

Google AppEngine - updating my webapp after deploy

friends! Im fairly new to web app world and I have a question regarding Google AppEngine functions. Ive installed the Launcher on my machine and signed up for the online platform (Python). Ive added …

Extract GPS coordinates from .docx file with python

I have some hectic task to do for which I need some help from python. Please see this word document.I am to extract texts and GPS coordinates from each row. There are currently over 100 coordinates in …

How to Serialize SQL data after a Join using Marshmallow? (flask extension)

I have 2 tables in SQL: class Zoo(db.Model):id = db.Column(db.Integer, primary_key=True)nome = db.Column(db.String(80), unique=True, nullable=False)idade = db.Column(db.Integer, unique=False, nullable=…

Python readline() is not reading a line with single space

I am reading a text file using readline(). My file contains below content with a space at second line:!" # $ % & When I print read values using-print("%s\n" % iso5_char)It prints-!&q…

Bisection search [duplicate]

This question already has answers here:Closed 11 years ago.Possible Duplicate:Using bisection search to determine I have posted other thread but it did not receive answers thus im trying to provide so…

What am i doing wrong with matplotlibs yticks?

My code is as follows (dont ask for the variable names, im german^^):import matplotlib.pyplot as plt import numpy as np strecke = [] zeit = []daten = open("BewegungBeschleunigung.csv")for i i…

Python- How to implement quick sort when middle element is the pivot?

There are many different versions of quickSort that pick pivot in different ways.Always pick the first element or the last element as the pivot Pick a random element as a pivot. Pick median as the pivo…