[原创] “玩板”+在STM32F7DISC上重玩micropython(5)

dcexpert   2020-2-19 16:38 楼主

有了LCD和TS驱动,就可以做一点复杂的演示了。下面是一个分形(mandelbrot)演示程序,首先绘制初始的图案,然后读取触摸屏输入,根据输入的手势进行缩放、移动等操作。


因为触摸屏驱动没有直接提供手势功能,因此做了一个简单的识别,通过检测单点和双点触摸以及触摸时间和移动距离,判断手势。先实现了单点触摸检测,并完成了图形的移动功能,下一步将缩放检测功能(争取尽快完成)。
 

为了加快显示速度和减少计算量,使用了guess方法计算分形。即先计算一个矩形块(这里设置为4x4大小)的4个顶点,如果它们是相同的,那么认为这个矩形区内部也是相同的,可以直接填充矩形。此外在移动时,也只计算变化的区域。

 

import lcdF7D as lcd
import tchF7D as ts
from time import sleep_ms, ticks_ms, ticks_diff
from random import randrange as rand
import gc

MAX_X = 480
MAX_Y = 272

MAX_ITER = 80
MAX_PAL = 256
pal = [i*16 for i in range(MAX_PAL)]

c = [0] * (MAX_X*MAX_Y//16)

ZoomFactor = 4
magnification = 1
WIN = [-0.5, 0, 6, 4]

def init():
    lcd.init()
    lcd.set_text_color(0x00FF00)
    ts.init(MAX_X, MAX_Y)

    lcd.set_layer_visible(0, 1)
    lcd.set_layer_visible(1, 0)
    lcd.select_layer(1)
    lcd.clear(0x40, 0)
    lcd.set_text_color(0x60, 0x888888)
    lcd.fill_rect(240 - 90, 136 - 20, 180, 40)
    lcd.set_text_color(0xA0, 0x00AA00)
    lcd.set_back_color(0x30, 0x888888)
    lcd.set_font(20)
    s = 'calculating'
    lcd.display_string_at(240 - len(s)*14//2, 136-20//2, 'calculating', 0)

    lcd.select_layer(0)
    lcd.clear(0)

init()

def randPAL():
    global pal
    pal = [rand(0xFFFFFF) for i in range(MAX_PAL)]

@micropython.native
def calc(c, ITER=MAX_ITER):
    z = c
    for i in range(ITER):
        z = z * z + c
        if abs(z) >= 4:
            return i
    return 0

# wr: cx(center x), cy(center y), width, height
# sr: sx(left), sy(top), width, height
def draw_fast_mandelbrot(wr = [-0.5, 0, 6, 4], sr = [0, 0, MAX_X, MAX_Y], ITER = MAX_ITER):

    print(wr, sr)

    lcd.set_layer_visible(1, 1)
    lcd.select_layer(0)
    lcd.set_text_color(0)
    lcd.fill_rect(sr[0], sr[1], sr[2], sr[3])

    t0 = ticks_ms()
    MX, MY = sr[2], sr[3]
    if MX == 0 or MY == 0:
        return 0

    x0, y0 = wr[0] - wr[2]/2, wr[1] - wr[3]/2
    dx, dy = wr[2]/MX, wr[3]/MY
    n = 0
    LXN, LYN = MX//4, MY//4

    for ix in range(0, MX, 4):
        for iy in range(0, MY, 4):
            z = x0 + dx * ix + (y0 + dy * iy) * 1j
            c[n] = calc(z, ITER)
            lcd.draw_pixel(sr[0]+ix, sr[1]+iy, pal[c[n]%MAX_PAL])
            n += 1

    for ix in range(0, MX, 4):
        for iy in range(0, MY, 4):
            n = ix * LYN //4 + iy//4
            if ix < MX-4 and iy < MY-4 and c[n] == c[n+1] and c[n] == c[n+LYN] and c[n] == c[n+LYN+1]:
                lcd.set_text_color(pal[c[n]%MAX_PAL])
                lcd.fill_rect(sr[0]+ix, sr[1]+iy, 5, 5)
            else:
                for i in range(1, 16):
                    z = x0 + dx * (ix + i//4)+ (y0 + dy * (iy + i%4)) * 1j
                    d = calc(z, ITER)
                    lcd.draw_pixel(sr[0]+ix+i//4, sr[1]+iy+i%4, pal[d%MAX_PAL])

    lcd.set_layer_visible(1, 0)
    return ticks_diff(ticks_ms(), t0)

def dealwith_drag(p1, p2):
    global WIN

    dx, dy = p2[0] - p1[0], p2[1] - p1[1]

    if dx*dx + dy*dy < 128:
        return

    dx = max(min(dx >> 3 << 3, 128), -128)
    dy = max(min(dy >> 3 << 3, 80), -80)
    wx = WIN[2]*dx/MAX_X
    wy = WIN[3]*dy/MAX_Y

    lcd.scroll(dx, dy)

    if dx >= 0:
        if dy >= 0:
            draw_fast_mandelbrot(wr = (WIN[0]-WIN[2]/2-wx/2, WIN[1]-wy, wx, WIN[3]), sr = (0, 0, dx, MAX_Y))
            draw_fast_mandelbrot(wr = (WIN[0]-wx/2, WIN[1]-WIN[3]/2-wy/2, WIN[2]-wx, wy), sr = (dx, 0, MAX_X-dx, dy))
        else:
            draw_fast_mandelbrot(wr = (WIN[0]-WIN[2]/2-wx/2, WIN[1]-wy, wx, WIN[3]), sr = (0, 0, dx, MAX_Y))
            draw_fast_mandelbrot(wr = (WIN[0]-wx/2, WIN[1]+WIN[3]/2-wy/2, WIN[2]-wx, -wy), sr = (dx, MAX_Y + dy, MAX_X-dx, -dy))
    else:
        if dy >= 0:
            draw_fast_mandelbrot(wr = (WIN[0]+WIN[2]/2-wx/2, WIN[1]-wy, -wx, WIN[3]), sr = (MAX_X+dx, 0, -dx, MAX_Y))
            draw_fast_mandelbrot(wr = (WIN[0]-wx/2, WIN[1]-WIN[3]/2-wy/2, WIN[2]-wx, wy), sr = (0, 0, MAX_X+dx, dy))
        else:
            draw_fast_mandelbrot(wr = (WIN[0]+WIN[2]/2-wx/2, WIN[1]-wy, -wx, WIN[3]), sr = (MAX_X+dx, 0, -dx, MAX_Y))
            draw_fast_mandelbrot(wr = (WIN[0]-wx/2, WIN[1]+WIN[3]/2-wy/2, WIN[2]-wx, -wy), sr = (0, MAX_Y + dy, MAX_X+dx, -dy))

    WIN[0] -= wx
    WIN[1] -= wy


def main():
    ts_g_drag = False
    ts_g_zoom = False
    ts_n = 0
    ts_t = 0
    ts_gd0 = [0, 0, 0, 0, 0]

    draw_fast_mandelbrot(wr = WIN)

    while 1:

        ts.get_state()
        ts_n = ts.touches()
        if ts_n > 0:
            if ts_n == 1:   # drag
                if not ts_g_drag:
                    ts_g_drag = True
                    ts_t = 0
                    ts_gd0 = ts.point_info(1)
                    print('Drag detect begin')
                else:
                    if ts_t <= 30:
                        ts_t += 1
                        if ts_t == 30:
                            print('Drag detect ok.')
                    ts_gd1 = ts.point_info(1)

            elif ts_n == 2: # zoom
                pass

            else:
                pass
        else:
            if ts_g_drag:
                #ts_g_drag = False
                if ts_t > 30:
                    print('Drag end.')
                    print(ts_gd0, ts_gd1)
                    dealwith_drag(ts_gd0, ts_gd1)

        if ts_n != 1:
            ts_g_drag = False
        if ts_n != 2:
            ts_g_zoom = False

        sleep_ms(20)


main()

 

运行效果

 

P00219-162213.gif

 


此内容由EEWORLD论坛网友dcexpert原创,如需转载或用于商业用途需征得作者同意并注明出处
 

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复