Author Topic: Voronoi Spiral gem  (Read 10188 times)

Tomaaz

  • Guest
Re: Voronoi Spiral gem
« Reply #15 on: August 27, 2016, 03:42:04 PM »
Okay, apart from BASIC I ported this to Pascal:

Did you port it to Lua, as well? I wonder how fast would it be.

B+

  • Guest
Re: Voronoi Spiral gem
« Reply #16 on: August 27, 2016, 04:51:09 PM »
OK, I wonder how fast it would be in Julia.

Tomaaz

  • Guest
Re: Voronoi Spiral gem
« Reply #17 on: August 27, 2016, 04:53:01 PM »
OK, I wonder how fast it would be in Julia.

It will be fast, but it will take ages to start.

ScriptBasic

  • Guest
Re: Voronoi Spiral gem
« Reply #18 on: August 27, 2016, 05:21:42 PM »
Here is a JavaScript version of a Voronoi Spiral variation.

Mopz

  • Guest
Re: Voronoi Spiral gem
« Reply #19 on: August 27, 2016, 06:36:09 PM »
Here is a JavaScript version of a Voronoi Spiral variation.

Looks beautiful. Looks like classic palette rotation :3

ScriptBasic

  • Guest
Re: Voronoi Spiral gem
« Reply #20 on: August 27, 2016, 10:37:53 PM »

Mike Lobanovsky

  • Guest
Re: Voronoi Spiral gem
« Reply #21 on: August 28, 2016, 03:12:00 AM »
@Cybermonkey:

Looks cool!

Again for fair comparison only, what CPU are you using? Is the FreeBASIC-translated output built against unoptimizing GAS or optimizing GCC? What bitness is your exe?

My exe feels fine unmodified under Ubuntu Wine, and surprisingly, under Mac OSX Lion Wine too even on a slightly slower Hackintosh! :)


@John:

Voronoi plasma looks impressive. Must be using prebuilt multi-threaded WebGL classes or something, but I'm too lazy to check tonight. :)
« Last Edit: August 28, 2016, 03:13:37 AM by Mike Lobanovsky »

ScriptBasic

  • Guest
Re: Voronoi Spiral gem
« Reply #22 on: August 28, 2016, 04:51:49 AM »
Quote from: Mike
Voronoi plasma looks impressive. Must be using prebuilt multi-threaded WebGL classes or something, but I'm too lazy to check tonight.

Nope. Just JavaScript.

D3 - Data-Driven Documents

Library Preview


Code: [Select]
<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="660" height="660"></canvas>
<script src="https://d3js.org/d3.v4.0.0-alpha.28.min.js"></script>
<script>

var canvas = d3.select("canvas").node(),
    context = canvas.getContext("2d"),
    width = canvas.width,
    height = canvas.height;

var sites = d3.range(100).map(function() { return [Math.random() * width, Math.random() * height]; }),
    cells = d3.voronoi().size([width, height]).polygons(sites),
    formatHex = d3.format("02x");

var colors = d3.range(256)
    .map(d3.scaleRainbow().domain([0, 255]))
    .map(function(c) { return d3.rgb(c); });

for (var i = 0; i < 256; ++i) {
  context.beginPath();
  cells.forEach(function(cell) {
    drawCell(cell);
    var p0 = cell.shift(),
        p1 = cell[0],
        t = Math.min(0.5, 4 / distance(p0, p1)),
        p2 = [p0[0] * (1 - t) + p1[0] * t, p0[1] * (1 - t) + p1[1] * t];
    cell.push(p2);
  });
  context.fillStyle = "#" + formatHex(i) + "0000";
  context.fill();
}

var source = context.getImageData(0, 0, width, height).data,
    targetBuffer = context.createImageData(width, height),
    target = targetBuffer.data;

for (var i = 0, y = 0; y < height; ++y) {
  for (var x = 0; x < width; ++x, i += 4) {
    target[i + 0] =
    target[i + 1] =
    target[i + 2] =
    target[i + 3] = 255;
  }
}

context.clearRect(0, 0, width, height);

d3.timer(function(elapsed) {
  for (var i = 0, y = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x, i += 4) {
      var c = colors[Math.floor(source[i] + elapsed / 10) % 256];
      target[i + 0] = c.r;
      target[i + 1] = c.g;
      target[i + 2] = c.b;
    }
  }
  context.putImageData(targetBuffer, 0, 0);
});

function drawCell(cell) {
  context.moveTo(cell[0][0], cell[0][1]);
  for (var i = 1, n = cell.length; i < n; ++i) context.lineTo(cell[i][0], cell[i][1]);
  context.closePath();
}

function distance(a, b) {
  var dx = a[0] - b[0], dy = a[1] - b[1];
  return Math.sqrt(dx * dx + dy * dy);
}

</script>

FYI: My next Script BASIC extension module. (hoping it's thread safe)
V7: Embedded JavaScript engine
« Last Edit: August 28, 2016, 07:44:25 AM by John »

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: Voronoi Spiral gem
« Reply #23 on: August 28, 2016, 08:17:27 AM »
@Cybermonkey:

Looks cool!

Again for fair comparison only, what CPU are you using? Is the FreeBASIC-translated output built against unoptimizing GAS or optimizing GCC? What bitness is your exe?

My exe feels fine unmodified under Ubuntu Wine, and surprisingly, under Mac OSX Lion Wine too even on a slightly slower Hackintosh! :)


-Computer-
Processor        : 6x AMD FX(tm)-6100 Six-Core Processor @ 3.3 GHz
Memory        : 8157MB
Operating System  : Ubuntu 16.04.1 LTS
Kernel        : Linux 4.4.0-34-generic (x86_64)
Default C Compiler : GNU C Compiler version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2)

I don't know what optimizing FBC does. I just invoke fbc voronoi.bas; the resulting exe is 64 Bit.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: Voronoi Spiral gem
« Reply #24 on: August 28, 2016, 10:00:19 AM »
Okay, here's the ChipmonkeyLua version (painted in the backbuffer):

Code: [Select]
points = 36 * 13
rad = math.pi /180
gem=700
cy = gem / 2
  ga = 10
  x={}
    y={}
    rd={}
    gr={}
    bl={}
    scale = 0.7
 
 visualpage (0)
 activepage (1)
 cls()     

time1=gettickcount()
for n = 0, points do
   x[n] = round (cy + scale * n * math.cos(rad * n * ga))
   y[n] = round (cy + scale * n * math.sin(rad * n * ga))
   if (x[n] < gem) and (x[n] > 0) and (y[n] < gem) and (y[n] > 0) then
     g = round (127 - math.abs(cy - x[n]) * 127 / cy  + 127 - math.abs(cy - y[n]) * 127 / cy);
    else
     g = 0
   end
   
   if (x[n] < gem) and (x[n] > 0) then
    r = round (255 - x[n] * 255 / gem)
   else 
     r = 0
   end
   
   if (y[n] < gem) and (y[n] > 0) then
    b = round (y[n] * 255 / gem)
    else 
    b = 0
   end
   rd [n]=r
   gr[n]=g
   bl[n]=b
   ink  (rgb (r, g, b))
   fillcircle(x[n], y[n], 2)
end

for xx = 0, gem do
   for yy = 0, gem do
      d = gem * gem + 1
      for i = 0, points do
         a = x[i] - xx
         b = y[i] - yy
         q = a * a + b * b
         if q < d then
          d = q
          kkl = i
         end
      end
  ink (rgb (rd[kkl],gr[kkl],bl[kkl]))
      pset (xx, yy);
   end
   
end
time2=gettickcount()
visualpage (1)
ink (0)
print ("Time: ".. ((time2-time1)/1000) .." seconds")

Time: over 87 seconds.

Cybermonkey

  • Administrator
  • *****
  • Posts: 0
Re: Voronoi Spiral gem
« Reply #25 on: August 28, 2016, 10:10:47 AM »
And just again for comparison if someone thinks I am cheating because I don't use PulsarLua. This time another Pascal version using the same graphics routines as the Lua example:
Code: [Select]
{$IFDEF Windows}
  {$APPTYPE GUI}
{$ENDIF}
program voronoi;

uses graphtools,ptcgraph,ptccrt,sysutils,math;

const points = 36 * 13;
const rad = pi /180;
const gem=700;
var   cy:integer = gem div 2;
  ga:integer = 10;
  x:array [0..points] of integer;
    y:array [0..points] of integer;
    rd:array [0..points] of integer;
    gr:array [0..points] of integer;
    bl:array [0..points] of integer;
    scale:float = 0.7;      
      n,r,g,b,xx,yy,i,d,q,a,kkl, time1, time2: integer;
     
   
BEGIN   

mode (3);
textsize (2);
setvisualpage (0);
setactivepage (1);
cleardevice;
time1:=gettickcount64;
for n := 0 to points do begin
   x[n] := round (cy + scale * n * cos(rad * n * ga));
   y[n] := round (cy + scale * n * sin(rad * n * ga));
   if (x[n] < gem) and (x[n] > 0) and (y[n] < gem) and (y[n] > 0) then begin
     g := round (127 - abs(cy - x[n]) * 127 / cy  + 127 - abs(cy - y[n]) * 127 / cy);
   end
   else begin
     g := 0;
   end;
   
   if (x[n] < gem) and (x[n] > 0) then begin
    r := round (255 - x[n] * 255 / gem);
   end
   else  begin
     r := 0;
    end;
   
   if (y[n] < gem) and (y[n] > 0) then begin
    b := round (y[n] * 255 / gem);
    end
    else  begin
    b := 0 ;
    end;
   rd [n]:=r;
   gr[n]:=g;
   bl[n]:=b;
   ink (r, g, b);
   fillcircle(x[n], y[n], 2);
end;

for xx := 0 to gem do begin
   for yy := 0 to gem do begin
      d := gem * gem + 1;
      for i := 0 to points do begin
         a := x[i] - xx;
         b := y[i] - yy;
         q := a * a + b * b;
         if q < d then begin
          d := q ;
          kkl := i;
         end;
      end;
  ink (rd[kkl],gr[kkl],bl[kkl]);
      pset(xx, yy);
   end;
   //redraw;
end;
time2:=gettickcount64;
setvisualpage (1);
ink (0,0,0);
OuttextXY (0,0,'Time: ' + FloatToStr ((time2-time1)/1000) + ' seconds');

getkey;
mode (0);


END.

Time: 1.655 seconds

Just for comparison: with my slow (but nice) notebook using an Intel Celeron N2940 (quadcore @ 1.83 GHz), I got the following times (all 32 Bit exe on a 64 Bit Windows 10 system - and all done working with the battery):
Free Pascal (Graph): 2.985 seconds
FreeBASIC (SDL2): 3.78 seconds
ChipmonkeyLua: 190.5 seconds
« Last Edit: August 28, 2016, 10:58:06 AM by Cybermonkey »

Mike Lobanovsky

  • Guest
Re: Voronoi Spiral gem
« Reply #26 on: August 28, 2016, 06:12:07 PM »
I don't know what optimizing FBC does. I just invoke fbc voronoi.bas; the resulting exe is 64 Bit.

FBC per se doesn't perform any optimizations. With such invokation, it translates BASIC to AT&T assembly and uses GAS as the backend. To the best of my knowledge, GAS isn't capable of optimizing anything either.

Invoking fbc -gen gcc voronoi.bas will force it to emit C output and use GCC as the back end. GCC has excellent optimization capabilities and your process times may improve considerably.

Mike Lobanovsky

  • Guest
Re: Voronoi Spiral gem
« Reply #27 on: August 28, 2016, 07:26:18 PM »
Nope. Just JavaScript

I probably failed to express myself clear. I meant the 2D canvas that the script is drawing to must be some sort of WebGL widget class to be able to perform color fills so quickly. The particular implementation is of course hidden from JavaScript and data interchange is wrapped in a set of familiarly sounding accessor methods like canvas.moveTo(), canvas.lineTo(), canvas.fillStyle(), canvas.fill(), etc. Those are the names of system WinAPIs from the standard Gdi32.dll library. :)

ScriptBasic

  • Guest
Re: Voronoi Spiral gem
« Reply #28 on: August 28, 2016, 07:38:41 PM »
Quote
Those are the names of system WinAPIs from the standard Gdi32.dll library. :)

I'm running it in Firefox on Linux.

I'm not sure how Firefox's canvas element works under the covers but I like the D3 library's use of it.


Tomaaz

  • Guest
Re: Voronoi Spiral gem
« Reply #29 on: August 28, 2016, 09:02:42 PM »
... and data interchange is wrapped in a set of familiarly sounding accessor methods like canvas.moveTo(), canvas.lineTo(), canvas.fillStyle(), canvas.fill(), etc. Those are the names of system WinAPIs from the standard Gdi32.dll library. :)

I'm pretty sure that is just a a coincidence. :)