Skip to content

[Ad] Fun with Scribus (Mandelbrot Set, Apfelmännchen) #217

Description

@flagsoft

Let's have some fun with Scribus.

Let's draw the Mandelbrot set, also known as Apfelmännchen.

But note: It's very slow. Maybe a general bug within Scribus, maybe we need a thread for drawing things. Run calculation things in a separate thread instead within the main-thread. (For bug reports and feature request please use: https://bugs.scribus.net/)
Anyway, thanks for this amazing application.

NOTE: Disable Undo function for document to calculate fast. This seems to be a Undo-bug within Scribus.

Image Image Image Image

Here is the code: (Black and White)

## Scribus 1.6.6
## Script > Execute Script... load python file. Wait.
## status:works

import scribus

def draw_mandelbrot():
    # Grid resolution (keep low for speed; vector objects are heavy)
    width_px = 60
    height_px = 60
    
    # Complex plane boundaries
    x_min, x_max = -2.0, 0.5
    y_min, y_max = -1.25, 1.25
    max_iter = 30
    
    # Layout positioning on the Scribus page
    start_x = 50
    start_y = 50
    box_size = 4
    
    if not scribus.haveDoc():
        scribus.newDocument(scribus.PAPER_A4, (10, 10, 10, 10), scribus.PORTRAIT, 1, scribus.UNIT_POINTS, scribus.PAGE_1, 0, 1)
    
    scribus.setRedraw(False)
    
    for row in range(height_px):
        py = y_min + (row / float(height_px)) * (y_max - y_min)
        for col in range(width_px):
            px = x_min + (col / float(width_px)) * (x_max - x_min)
            
            c = complex(px, py)
            z = 0j  # Corrected Python complex zero definition
            iteration = 0
            
            while abs(z) <= 2 and iteration < max_iter:
                z = z*z + c
                iteration += 1
                
            if iteration == max_iter:
                # Point is inside the Mandelbrot set
                x_pos = start_x + (col * box_size)
                y_pos = start_y + (row * box_size)
                rect = scribus.createRect(x_pos, y_pos, box_size, box_size)
                scribus.setFillColor("Black", rect)
                scribus.setLineColor("None", rect)

    scribus.setRedraw(True)
    scribus.docChanged(True)

draw_mandelbrot()

Color:

##

import sys
import scribus

import time
from datetime import datetime



def force_ui_update(message=""):
	if message:
		scribus.statusMessage(message)

	if hasattr(scribus, 'redrawAll'):
		scribus.redrawAll()
	elif hasattr(scribus, 'redraw'):
		scribus.redraw()





def draw_colored_mandelbrot():


    now = datetime.now()
    print("- BEGIN:", now.strftime("%Y-%m-%d %H:%M:%S") )
    DEBUG_start = time.time()


    # Grid resolution (keep under 80x80 for fast rendering)
    width_px = 200
    height_px = 200
    #width_px = 40
    #height_px = 40
    #width_px = 30
    #height_px = 30
    #width_px = 65
    #height_px = 65


    ## Seahorse Valley: x = -0.75, y = 0.1
    
    # Complex plane boundaries
    x_min, x_max = -0.75, 0.5
    y_min, y_max = 0.1, 1.25

    #x_min, x_max = -2.0, 0.5
    #y_min, y_max = -1.25, 1.25



    max_iter = 200
    #max_iter = 120
    #max_iter = 60
    #max_iter = 10
    #max_iter = 15
    #max_iter = 30
    
    # Page position and cell dimensions
    start_x = 50
    start_y = 50
    box_size = 2
    #box_size = 4
    
    if not scribus.haveDoc():
        scribus.newDocument(scribus.PAPER_A4, (10, 10, 10, 10), scribus.PORTRAIT, 1, scribus.UNIT_POINTS, scribus.PAGE_1, 0, 1)
    
    # Define colors in CMYK format (0 to 255)
    scribus.defineColor("Mandel_Black", 0, 0, 0, 255)


    ## -- color palette    
    for i in range(max_iter):
        t = i*(max_iter/10) / float(max_iter)

        #t = i*40 / float(max_iter)
        #t = i*10 / float(max_iter)
        #t = i / float(max_iter)

        #c = int(0)
        #y = int(t * 255)
        #m = int((1.0 - t) * 255)
        #k = int(0)


        ## CMYK gradient mapping from light yellow to deep red/magenta
        c = int(0)
        m = int(t * 255)
        y = int((1.0 - t) * 255)
        k = int(0)

        scribus.defineColor(f"Mandel_Iter_{i}", c, m, y, k)



    scribus.setRedraw(False)
    
    for row in range(height_px):
        py = y_min + (row / float(height_px)) * (y_max - y_min)
        for col in range(width_px):
            px = x_min + (col / float(width_px)) * (x_max - x_min)
            
            c_val = complex(px, py)
            z = 0j
            iteration = 0
            
            while abs(z) <= 2 and iteration < max_iter:
                z = z*z + c_val
                iteration += 1
                
            x_pos = start_x + (col * box_size)
            y_pos = start_y + (row * box_size)

            ## -- DRAW
            rect = scribus.createRect(x_pos, y_pos, box_size, box_size)
            
            if iteration >= max_iter:
                scribus.setFillColor("Mandel_Black", rect)
                scribus.setLineColor("Mandel_Black", rect)
            else:
                scribus.setFillColor(f"Mandel_Iter_{iteration}", rect)
                scribus.setLineColor(f"Mandel_Iter_{iteration}", rect)


        # Flush the UI buffer every 10 iterations
        if row % 1 == 0:
            force_ui_update(f"Generating item row:{row} of with_px:{height_px}...")




    force_ui_update("Done!")

    scribus.setRedraw(True)
    scribus.docChanged(True)

    now2 = datetime.now()
    print("- END:", now2.strftime("%Y-%m-%d %H:%M:%S") )
    DEBUG_end = time.time()
    print("- Execution time [seconds]: ", DEBUG_end - DEBUG_start)


draw_colored_mandelbrot()


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions