## digitalmars.D.learn - Procedural drawing using ndslice

• Claude (59/59) Feb 11 2016 Hello,
• John Colvin (6/65) Feb 11 2016 I had a go at trying the sort of thing you are talking about:
• =?UTF-8?Q?Ali_=c3=87ehreli?= (52/109) Feb 11 2016 Here is a very very rough proof of concept:
• Claude (5/5) Feb 12 2016 Thanks for your replies, John and Ali. I wasn't sure I was clear.
Claude <no no.no> writes:
```Hello,

I come from the C world and try to do some procedural terrain
generation, and I thought ndslice would help me to make things
look clean, but I'm very new to those semantics and I need help.

Here's my problem: I have a C-style rough implementation of a
function drawing a disk into a 2D buffer. Here it is:

import std.math;
import std.stdio;

void draw(ref float[16][16] buf, int x0, int y0, int x1, int y1)
{
float xc = cast(float)(x0 + x1) / 2;
float yc = cast(float)(y0 + y1) / 2;
float xr = cast(float)(x1 - x0) / 2;
float yr = cast(float)(y1 - y0) / 2;

float disk(size_t x, size_t y)
{
float xx, yy;
xx = (x - xc) / xr;
yy = (y - yc) / yr;
return 1.0 - sqrt(xx * xx + yy * yy);
}

for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
buf[x][y] = disk(x, y);
writef(" % 3.1f", buf[x][y]);
}
writeln("");
}
}

void main()
{
float[16][16] buf;

draw(buf, 2, 2, 10, 10);
}

The final buffer contains values where positive floats are the
inside of the disk, negative are outside, and 0's represents the
perimeter of the disk.

I would like to simplify the code of draw() to make it look more
something like:

Slice!(stuff) draw(int x0, int y0, int x1, int y1)
{
float disk(size_t x, size_t y)
{
// ...same as above
}

return Slice!stuff.something!disk.somethingElseMaybe;
}

Is it possible?

Do I need to back-up the slice with an array, or could the slice
be used lazily and modified as I want using some other drawing
functions.

auto diskNoiseSlice = diskSlice.something!AddNoiseFunction;

... until I do a:

auto buf = mySlice.array;

... where the buffer would be allocated in memory and filled with
the values according to all the drawing primitives I used on the
slice.
```
Feb 11 2016
John Colvin <john.loughran.colvin gmail.com> writes:
```On Thursday, 11 February 2016 at 13:05:41 UTC, Claude wrote:
Hello,

I come from the C world and try to do some procedural terrain
generation, and I thought ndslice would help me to make things
look clean, but I'm very new to those semantics and I need help.

Here's my problem: I have a C-style rough implementation of a
function drawing a disk into a 2D buffer. Here it is:

import std.math;
import std.stdio;

void draw(ref float[16][16] buf, int x0, int y0, int x1, int y1)
{
float xc = cast(float)(x0 + x1) / 2;
float yc = cast(float)(y0 + y1) / 2;
float xr = cast(float)(x1 - x0) / 2;
float yr = cast(float)(y1 - y0) / 2;

float disk(size_t x, size_t y)
{
float xx, yy;
xx = (x - xc) / xr;
yy = (y - yc) / yr;
return 1.0 - sqrt(xx * xx + yy * yy);
}

for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
buf[x][y] = disk(x, y);
writef(" % 3.1f", buf[x][y]);
}
writeln("");
}
}

void main()
{
float[16][16] buf;

draw(buf, 2, 2, 10, 10);
}

The final buffer contains values where positive floats are the
inside of the disk, negative are outside, and 0's represents
the perimeter of the disk.

I would like to simplify the code of draw() to make it look
more something like:

Slice!(stuff) draw(int x0, int y0, int x1, int y1)
{
float disk(size_t x, size_t y)
{
// ...same as above
}

return Slice!stuff.something!disk.somethingElseMaybe;
}

Is it possible?

Do I need to back-up the slice with an array, or could the
slice be used lazily and modified as I want using some other
drawing functions.

auto diskNoiseSlice = diskSlice.something!AddNoiseFunction;

... until I do a:

auto buf = mySlice.array;

... where the buffer would be allocated in memory and filled
with the values according to all the drawing primitives I used
on the slice.

I had a go at trying the sort of thing you are talking about:
http://dpaste.dzfl.pl/8f9da4f4cc34

That won't work with std.experimental.ndslice in 2.070.0, so
either use dmd git master or use the latest version of ndslice in
mir (https://github.com/DlangScience/mir).
```
Feb 11 2016
=?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
```On 02/11/2016 05:05 AM, Claude wrote:
Hello,

I come from the C world and try to do some procedural terrain
generation, and I thought ndslice would help me to make things look
clean, but I'm very new to those semantics and I need help.

Here's my problem: I have a C-style rough implementation of a function
drawing a disk into a 2D buffer. Here it is:

import std.math;
import std.stdio;

void draw(ref float[16][16] buf, int x0, int y0, int x1, int y1)
{
float xc = cast(float)(x0 + x1) / 2;
float yc = cast(float)(y0 + y1) / 2;
float xr = cast(float)(x1 - x0) / 2;
float yr = cast(float)(y1 - y0) / 2;

float disk(size_t x, size_t y)
{
float xx, yy;
xx = (x - xc) / xr;
yy = (y - yc) / yr;
return 1.0 - sqrt(xx * xx + yy * yy);
}

for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
buf[x][y] = disk(x, y);
writef(" % 3.1f", buf[x][y]);
}
writeln("");
}
}

void main()
{
float[16][16] buf;

draw(buf, 2, 2, 10, 10);
}

The final buffer contains values where positive floats are the inside of
the disk, negative are outside, and 0's represents the perimeter of the
disk.

I would like to simplify the code of draw() to make it look more
something like:

Slice!(stuff) draw(int x0, int y0, int x1, int y1)
{
float disk(size_t x, size_t y)
{
// ...same as above
}

return Slice!stuff.something!disk.somethingElseMaybe;
}

Is it possible?

Do I need to back-up the slice with an array, or could the slice be used
lazily and modified as I want using some other drawing functions.

auto diskNoiseSlice = diskSlice.something!AddNoiseFunction;

... until I do a:

auto buf = mySlice.array;

... where the buffer would be allocated in memory and filled with the
values according to all the drawing primitives I used on the slice.

Here is a very very rough proof of concept:

import std.stdio;

struct LazyLine(Element, int Length, alias func) {
int y;

Element opIndex(int x) {
return func(y, x);
}
}

struct LazyRect(Element, int Height, int Width, alias func) {

Element opIndex(A...)(A args) {
const y = args[0];
const x = args[1];
auto line = LazyLine!(Element, Width, func)(y);

return line[x];
}

auto chain(alias nextFunc)() {
return NextLazyRect!(Element, Height, Width, nextFunc,
typeof(this))(this);
}
}

struct NextLazyRect(Element, int Height, int Width, alias func,
PreviousLazyRect) {
PreviousLazyRect previous;

Element opIndex(A...)(A args) {
const y = args[0];
const x = args[1];
return func(previous[y, x]);
}
}

auto abc(int line, int row) {
return line * 10 + row;
}

auto xyz(float f) {
return f / 10;
}

void main() {
auto rect = LazyRect!(float, 3, 5, abc)().chain!xyz;

foreach (line; 0 .. 5) {
foreach (row; 0 .. 4) {
writef("%6.1f", rect[line, row]);
}
writeln();
}
}

Output:

0.0   0.1   0.2   0.3
1.0   1.1   1.2   1.3
2.0   2.1   2.2   2.3
3.0   3.1   3.2   3.3
4.0   4.1   4.2   4.3

Ali
```
Feb 11 2016
Claude <no no.no> writes:
```Thanks for your replies, John and Ali. I wasn't sure I was clear.

I'm going to try to see if I can fit Ali concept (totally lazy,
which is what I was looking for) within ndslices, so that I can
also use it in 3D and apply window() function to the result and
mess around with it.
```
Feb 12 2016