Crossing

-- crossing

-- Use this function to perform your initial setup
function setup()
    displayMode(OVERLAY)
    
    dataNum = 100
    
    
    print("Hello World!")
    displayMode(FULLSCREEN)
 --   backingMode(RETAINED)
    frame = 1
    done = false
    
    data={}
    dataBuf={}
    for n=1,dataNum do
        table.insert(dataBuf,n)
    end
    for n=1,dataNum do
        n = table.remove(dataBuf,math.random(1,#dataBuf))
        table.insert(data, 
        {
            num = n, 
            col= randomColor(),
            pnt={},
            velocity=math.random(20,100)
        })
    end
    calcAllCrossingPoint()
end

-- x1 = {s=n, e=n}
function calcCrossingPoint(x1,y1,x2,y2)
    mA = matrix(
        -(y1.e - y1.s),      x1.e - x1.s,  0, 0,  
        -(y2.e - y2.s),      x2.e - x2.s,  0, 0,
        0,0,1,0,
            0,0,0,1
        )
        invA = mA:inverse() 
    mB = matrix(
        x1.e * y1.s - y1.e * x1.s   , 0,0,0,
        x2.e * y2.s - y2.e * x2.s   , 0,0,0,
        0,0,0,0,
        0,0,0,0
    )
    mAns = invA * mB
    return mAns[1], mAns[5]
end

function randomColor()
    local col= color(
                math.random(128,255),
                math.random(64,128),
                math.random(64,128))
    return col
end

function setParam()
    local hMargin = 0.9
    local vMargin = 0.9
    local param = {
        h = HEIGHT * vMargin,
        posy = HEIGHT * (1 - vMargin)/2,
        l = WIDTH * (1 - hMargin)/2,
        r = WIDTH * ((1 - hMargin)/2 + hMargin),
        step = WIDTH * hMargin/dataNum
    }
    return param
end

function draw()
    if done == true then
  --      return
    end
    frame = frame + 1
 --   background(40, 40, 50)
    strokeWidth(4)
    stroke(158, 183, 39, 255)
    local param = setParam()
    line(param.l, param.posy, param.r, param.posy)
    line(param.l, param.posy + param.h, param.r, param.posy + param.h)
    strokeWidth(1)
    
    local x1,y1,x2,y2={s=0,e=0},{s=0,e=0},{s=0,e=0},{s=0,e=0}
    for k,v in ipairs(data) do
    --  if (frame % dataNum) > k then
    --    if (frame          ) > k then
            stroke(v.col)
            fill(242, 24, 24, 255)
            strokeWidth(1)
            x1, y1 = calcPos(k, v.num,param)
            line(x1.s, y1.s, x1.e, y1.e)
            for i,o in ipairs(v.pnt) do
                strokeWidth(0)
                fill(randomColor())
                ellipse(o.x, o.y, math.random(2,12))
         --       o.y = o.y - v.velocity
                if o.y < param.posy then
                    v.velocity = 0
                end
            end
      --  end
    end
    done = true
end


function calcAllCrossingPoint()
    local param = setParam()
    local x1,y1,x2,y2={s=0,e=0},{s=0,e=0},{s=0,e=0},{s=0,e=0}
    for k,v in ipairs(data) do
        x1, y1 = calcPos(k, v.num,param)
        v.x1y1 = {x1=x1, y1=y1}
        for n=k+1,dataNum do
            if v.num > data[n].num then
                x2, y2 = calcPos(n, data[n].num, param)
                local x,y=calcCrossingPoint(x1,y1,x2,y2)
                table.insert(v.pnt, {x=x,y=y})
            end
        end
    end
end


function calcPos(s, e, param)
    local x = {s = param.l + s * param.step,     
                e = param.l+ e * param.step}
    local y = {s = param.posy,e = param.posy+param.h}
    return x, y
end

-- This function gets called once every frame

pretty! =D>

@cuvota I like the effect you created. I have something similar I wrote long ago, but I like the way yours looks a lot better.


displayMode(FULLSCREEN)

function setup()
    tab={}
    tab1={}
    tab2={}
    for z=1,15 do
        table.insert(tab,vec4(math.random(WIDTH),HEIGHT,math.random(WIDTH),0))  
        table.insert(tab1,vec4(0,math.random(HEIGHT),WIDTH,math.random(HEIGHT)))       
    end
end

function draw()
    background(30, 60, 74, 255)
    stroke(255)
    strokeWidth(2)
    for a,b in pairs(tab) do
        line(b.x,b.y,b.z,b.w)
        b.x=b.x+1
        if b.x>WIDTH then
            b.x=0
        end
        b.z=b.z+1
        if b.z>WIDTH then
            b.z=0
        end
    end
    for a,b in pairs(tab1) do
        line(b.x,b.y,b.z,b.w)
        b.y=b.y+1
        if b.y>HEIGHT then
            b.y=0
        end
        b.w=b.w+1
        if b.w>HEIGHT then
            b.w=0
        end
    end
    tab2={}
    for a,b in pairs(tab) do
        for c,d in pairs(tab1) do
            calc(vec2(b.x,b.y),vec2(b.z,b.w),vec2(d.x,d.y),vec2(d.z,d.w))
        end
    end
    for a,b in pairs(tab) do
        for c,d in pairs(tab) do
            calc(vec2(b.x,b.y),vec2(b.z,b.w),vec2(d.x,d.y),vec2(d.z,d.w))
        end
    end
    for a,b in pairs(tab1) do
        for c,d in pairs(tab1) do
            calc(vec2(b.x,b.y),vec2(b.z,b.w),vec2(d.x,d.y),vec2(d.z,d.w))
        end
    end
    noStroke()
    for a,b in pairs(tab2) do
        fill(math.random(255),math.random(255),math.random(255))
        ellipse(b.x,b.y,20)
    end
end

function calc(a,b,c,d)    -- calculate intercept point
    x1=a.x y1=a.y x2=b.x y2=b.y x3=c.x y3=c.y x4=d.x y4=d.y    
    x12=x1-x2 y12=y1-y2 x34=x3-x4 y34=y3-y4     
    c=x12*y34-y12*x34  
    if math.abs(c) > 0.01 then
        a=x1*y2-y1*x2 b=x3*y4-y3*x4 x=(a*x34-b*x12)/c y=(a*y34-b*y12)/c    
    end
    if x>math.min(x1,x2) and x<math.max(x1,x2) and
          y>math.min(y1,y2) and y<math.max(y1,y2) and
          x>math.min(x3,x4) and x<math.max(x3,x4) and
          y>math.min(y3,y4) and y<math.max(y3,y4) then
        table.insert(tab2,vec2(x,y))
    end
end

@cuvota An interesting effect with your program is to set dataNum=10, run the program, and then keep pressing the replay button.

I found wonderful and fantastic figure, thank you for your comment.
also taking snapshot makes another effect. I fully enjoyed.

change the beginning of setup for this

function setup()
    displayMode(OVERLAY)

    dataNum = 10

    tween.delay(1,restart)

to get automatic updates