How to randomly fill a space in one dimension? - random

I would like to know how can I randomly fill a space with a set number of items and a target size, for example given the number of columns = 15 and a target size width = 320, how can I randomly distribute the columns width to fill the space? like shown in the image below if possible any sort of pseudo-code or algorithm will do

One way to partition your 320 pixels in 15 random "columns" is to do it uniformly, i.e., every column width follows the same distribution.
For this, your actually need a uniform distribution on the simplex. The first way to achieve is the one described by yi_H, and is probably the way to go:
Generate 14 uniform integers between 0 and 320.
Keep regenerating any number that has already been chosen, so that you end up with 14 distinct numbers
Sort them
Your columns bounds are given by two consecutive random numbers.
If you have a minimum width requirement (e.g., 1 for non-empty columns), remove it 15 times from your 320 pixels, generate the numbers in the new range and make the necessary adjustments.
The second way to achieve a uniform point on a simplex is a bit more involved, and not very well suited with discrete settings such as pixels, but here it is in brief anyway:
Generate 15 exponential random variables with same shape parameter (e.g. 1)
Divide each number by the total, so that each is in [0,1]
Rescale those number by multiplying them by 320, and round them. These are your column widths
This is not as nice as the first way, since with the rounding you may end with a total bigger or smaller than 320, and you may have columns with 0 width... The only advantage is that you don't need to perform any sort (but you have to compute logarithms... so all in all, the first way is the way to go).
I should add that if you do not necessarily want uniform random filling, then you have a lot more algorithms at your disposal.
Edit: Here is a quick implementation of the first algorithm in Mathematica. Note that in order to avoid generating points until they are all different, you can just consider that an empty column has a width of 1, and then a minimum width of 2 will give you columns with non-empty interior:
min = 2;
total = 320;
height = 50;
n = 15;
x = Sort[RandomInteger[total - n*min - 1, n - 1]] + Range[n - 1]*min
Graphics[{Rectangle[{-2, 0}, {0, height}], (*left margin*)
Rectangle[{#, 0}, {# + 1, height}] & /# x, (*columns borders*)
Rectangle[{total, 0}, {total + 2, height}]}, (*right margin*)
PlotRange -> {{-2, total + 2}, {0, height}},
ImageSize -> {total + 4, height}]
with gives the following example output:
Edit: Here is the modified javascript algorithm (beware, I have never written Javascript before, so there might be some errors\poor style):
function sortNumber(a,b)
{
return a - b;
}
function draw() {
var canvas = document.getElementById( "myCanvas" );
var numberOfStrips = 15;
var initPosX = 10;
var initPosY = 10;
var width = 320;
var height = 240;
var minColWidth = 2;
var reducedWidth = width - numberOfStrips * minColWidth;
var separators = new Array();
for ( var n = 0; n < numberOfStrips - 1; n++ ) {
separators[n] = Math.floor(Math.random() * reducedWidth);
}
separators.sort(sortNumber);
for ( var n = 0; n < numberOfStrips - 1; n++ ) {
separators[n] += (n+1) * minColWidth;
}
if ( canvas.getContext ) {
var ctx = canvas.getContext( "2d" );
// Draw lines
ctx.lineWidth = 1;
ctx.strokeStyle = "rgb( 120, 120, 120 )";
for ( var n = 0; n < numberOfStrips - 1; n++ ) {
var newPosX = separators[n];
ctx.moveTo( initPosX + newPosX, initPosY );
ctx.lineTo( initPosX + newPosX, initPosY + height );
}
ctx.stroke();
// Draw enclosing rectangle
ctx.lineWidth = 4;
ctx.strokeStyle = "rgb( 0, 0, 0 )";
ctx.strokeRect( initPosX, initPosY, width, height );
}
}
Additionally, note that minColWidth should not be bigger than a certain value (reducedWidth should not be negative...), but it is not tested in the algorithm. As stated before, us a value of 0 if you don't mind two lines on one another, a value of 1 if you don't mind two lines next to each other, and a value of 2 or more if you want non-empty columns only.

Create 14 unique numbers in the range (0,320). Those will be the x position of the bars.
Create random number, compare with previous ones, store it.
If consecutive lines aren't allowed, also check that it doesn't equal with any previous+-1.

Related

Is there an algorithm for automatic sizing and distributing squares/rectangles in a window?

I tried to find such an algorithm but I did not succeed so far, I hope you can help me. Thanks in advance!
So my problem is: I have a canvas. By clicking a button I can create a rectangle. When I have one rectangle, it is drawn to occupy most of the canvas. When I push it again, a new rectangle appears and then the two rectangles are redrawn to occupy each almost half of the available canvas. Then a third rectangle is created, and the three rectangles are distributed in two rows, in order to maintain certain proportions between length and width of each rectangle, occupying as much canvas as possible. And so on for n rectangles see image:
Is there any well-known algortighm(s) for doing this?
Thank you!
Your rectangles are all of the same size, so your task is to find the optimal number of rows and columns for your layout. The layout consists of a bounding rectangle, the number of rectangles k and a preferred width-to-height ratio α* plus a gap d between the rectangles:
const box = {
count: 7,
alpha: 1.2,
gap: 8,
nrow: 0, // to be determined ...
ncol: 0, // ...
width: 0, // ...
height: 0, // ...
};
A very simple algorithm would find a first guess for the number of columns m based on the input and then try out several m to find the maxium area while maintaining a reasonable aspect ratio.
Your overall area is A = W · H. The area of one box is a = w · h or a = h / α where α = w / h. A theoretical maximum area (if the gap were 0) is a* = A / k, where k is the number of rectangles. You can use this to estimate a first guess for w and there fore for the number of columns, m.
The "score" for our optimization is the area, which must be maximized. In order not to allow unpleasant aspect ratios, we incorporate the current aspect ratio α by dividing the score by the square of the error (α − α*)².
Here's a way this could be implemented:
function layout(canvas) {
let A = canvas.width * canvas.height;
let a = A / box.count;
let x = Math.sqrt(a * box.alpha);
let m = (canvas.width / x) | 0 - 2;
if (m < 1) m = 1;
let best = 0.0;
for (;;) {
let n = (((box.count - 1) / m) | 0) + 1;
let w = (canvas.width - (m - 1) * box.gap) / m;
let h = (canvas.height - (n - 1) * box.gap) / n;
if (h < 0) h = 0;
if (w < 0) w = 0;
let alpha = w / h;
let area = box.count * (w + box.gap) * (h + box.gap);
let dalpha = alpha - box.alpha;
let score = area / (dalpha * dalpha);
if (score < best) break;
box.width = w;
box.height = h;
box.ncol = m;
box.nrow = n;
best = score;
m++;
}
}
There's certainly room for improvement, for example when guessing the first shot. You can play with a rough implementation on jsbin.

How can I tile an image into patches of (constant) arbitrary size at (constant) arbitrary stride in MATLAB?

I have an image of arbitrary dimensions ROWS and COLS. I want to tile this image into patches of arbitrary, but constant size blockSize = [blockSizeR, blockSizeC], given an arbitrary, but constant stride stride = [strideR, strideC]. When the number of patches in row or column direction times the respective block size doesn't equal the number of rows or columns, respectively (i.e. if there were spare rows or columns), I don't care about them (i.e. they can be ignored). It's sufficient if the image is tiled into all possible patches that fit completely into the image starting from the top left pixel.
There is a bunch of possible solutions floating around the web, but some don't allow overlap, some don't allow outputs if there are spare rows or columns, some are making inefficient use of for loops.
The closest thing to what I need is probably the solution posted on https://de.mathworks.com/matlabcentral/answers/330357-how-do-i-store-a-series-of-rgb-images-in-a-2d-array:
%img: source image
stride = [5, 5]; %height, width
blocksize = [11, 11]; %height, width
tilescount = (size(img(:, :, 1)) - blocksize - 1) / stride + 1;
assert(all(mod(tilescount, 1) == 0), 'cannot divide image into tile evenly')
tiles = cell(tilescount);
tileidx = 1;
for col = 1 : stride(2) : size(img, 2 ) - blocksize(2)
for row = 1 : stride(1) : size(img, 1) - blocksize(1)
tiles{tileidx} = img(row:row+stride(1)-1, col:col+stride(2)-1, :);
tileidx = tileidx + 1;
end
end
However, it also seems to work only if there are no spare rows or columns. How can I adapt that to an efficient solution for images with an arbitrary number of channels (I seek to apply it on both single-channel images and RGB images)?
The code above did not fully work, so I came up with the following solution based on it. Variable names are chosen such that they are self-explanatory.
tilesCountR = floor((ROWS - rowBlockSize - 1) / rowStride + 1);
tilesCountC = floor((COLS - colBlockSize - 1) / colStride + 1);
tiles = cell(tilesCountR * tilesCountC,1);
tileidx = 1;
for col = 1 : colStride : COLS - colBlockSize
for row = 1 : rowStride : ROWS - rowBlockSize
tiles{tileidx} = img(row:row+rowBlockSize-1, col:col+colBlockSize-1, :);
tileidx = tileidx + 1;
end
end

Skipping some axis labels in a plot with imagesc

I have created a big heat map using matlab's imagesc command. It plots the error output for each combination of the values in x and y axes. As can be seen in the figure there are too many axes labels. This might become even denser as I plan to increase the number of points in both x and y axes - which means I will get more outputs on a finer grid.
I want to be flexible with the labels, and skip some of them. I want to do this for both X and Y. I also want to be flexible with the "ticks" and draw either all of them or maybe skip some of them. Keep in mind that both the X and Y values are not increasing in order, at first the increment is 0.01 for 9 points, then 0.1, then 1 or 3 or whatever. I will change these increments too.
I tried to show what I want the graph look like in the second image. I want roughly the labels shown in red boxes only. As I said these are not set values, and I will make the increments smaller which will lead to denser plot.
Thank you for your help.
OS: Windows 7, 8 (64 bit)
Matlab version: Matlab 2014 a
You can manipulate the ticks and labels like this:
ticksarray=[1 33 41 100 ...] % edit these to whatever you want
tickslabels={'1', '33', '41', '100'; ...} % match the size of both arrays
set(gca,'XTick',ticksarray)
set(gca,'XTickLabel',tickslabels)
The same thing applies to the y-axis.
Small working example:
x=1:100;
y=2*x.^2-3*x+2;
plot(x,y)
ticksarray=[1 33 41 100];
tickslabels={'1', '33', '41', '100'};
set(gca,'XTick',ticksarray)
set(gca,'XTickLabel',tickslabels)
Example:
figure(1)
load clown
subplot(211)
imagesc(X);
subplot(212)
imagesc(X);
h = gca;
Now you can either set a maximum number of labels per axis:
%// define maximum number of labels
maxLabel = 3;
h.XTick = linspace(h.xlim(1),h.xlim(2),maxLabel);
h.YTick = linspace(h.ylim(1),h.ylim(2),maxLabel);
or define how many labels should be skipped:
%// define number of labels to skip
skipLabel = 2;
h.XTick = h.XTick(1:skipLabel:end);
h.YTick = h.YTick(1:skipLabel:end)
You can also get a different number of ticks and labels, more complicated though:
maxLabel = 3;
maxTicks = 6;
h.XTick = linspace(h.xlim(1),h.xlim(2),maxTicks);
h.YTick = linspace(h.ylim(1),h.ylim(2),maxTicks);
h.XTickLabel( setdiff( 1:maxTicks, 1:maxTicks/maxLabel:maxTicks ) ) = repmat({''},1,maxTicks-maxLabel);
h.YTickLabel( setdiff( 1:maxTicks, 1:maxTicks/maxLabel:maxTicks ) ) = repmat({''},1,maxTicks-maxLabel);
If you use a prior version of Matlab 2014b, then you will need the set command to set all properties:
%// define maximum number of labels
maxLabel = 3;
Xlim = get(h,'Xlim');
Ylim = get(h,'Ylim');
set(h,'XTick', linspace(Xlim(1),Xlim(2),maxLabel));
set(h,'YTick', linspace(Ylim(1),Ylim(2),maxLabel));
%// or define number of labels to skip
skipLabel = 2;
XTick = get(h,'XTick');
YTick = get(h,'YTick');
set(h,'XTick', XTick(1:skipLabel:end));
set(h,'YTick', YTick(1:skipLabel:end));
%// or combined
maxLabel = 3;
maxTicks = 6;
Xlim = get(h,'Xlim');
Ylim = get(h,'Ylim');
set(h,'XTick', linspace(Xlim(1),Xlim(2),maxTicks));
set(h,'YTick', linspace(Ylim(1),Ylim(2),maxTicks));
XTickLabel = cellstr(get(h,'XTickLabel'));
YTickLabel = cellstr(get(h,'YTickLabel'));
XTickLabel( setdiff( 1:maxTicks, 1:maxTicks/maxLabel:maxTicks ),: ) = repmat({''},1,maxTicks-maxLabel);
YTickLabel( setdiff( 1:maxTicks, 1:maxTicks/maxLabel:maxTicks ),: ) = repmat({''},1,maxTicks-maxLabel);
set(h,'XTickLabel',XTickLabel);
set(h,'YTickLabel',YTickLabel);
After applying the second method proposed by #thewaywewalk I got the second figure below. Apparently the labels need to be structured as well, because they only take the first so many labels.
Then I tried to manipulate the labels as shown below, and got the third image.
skipLabel = 2;
XTick = get(h,'XTick');
YTick = get(h,'YTick');
set(h,'XTick', XTick(1:skipLabel:end));
set(h,'YTick', YTick(1:skipLabel:end));
XTickLabel = get(h,'XTickLabel');
labelsX = cell( length(1: skipLabel:length(XTick)) , 1);
j = 1;
for i = 1: skipLabel:length(XTick)
labelsX{j} = XTickLabel(i, :);
j = j + 1;
end
set(h,'XTickLabel', labelsX);
YTickLabel = get(h,'YTickLabel');
labelsY = cell( length(1: skipLabel:length(YTick)) , 1);
j = 1;
for i = 1: skipLabel:length(YTick)
labelsY{j} = YTickLabel(i, :);
j = j + 1;
end
set(h,'YTickLabel', labelsY);
The Y axis labels seem to be in place as before (right next to tick), however the X axis labels seem to be shifted to the left a little. How can I correct this?
Another note: How can I change the scientific values into normal numbers? Also, probably there is a better approach at manipulating the labels.

Midpoint Displacement 2D algorithm producing unusual patterns

I'm having difficulties with the Midpoint Displacement Algorithm using Haxe. I am implementing this by following the steps found here.
First, create an array that represents a blank map. You begin by giving the four corners a random value.
In this square, create the middle point by averaging the four corners and adding a small 'error', or random value. Then create the midpoints of the 4 sides by averaging the two corners each is between. After these steps, you are left with 4 squares. Repeat the steps:
Create the middle point by averaging the four corners and adding a small 'error'.
Create the midpoint of each side by averaging the two corners each point is between.
Each iteration, make the range of the RNG smaller. That way the original few points can have pretty large variation, but the later points only get tiny adjustments. This ensures the right amount of detail in an image.
Here is the function I've written to perform these steps and then normalize the values:
public static function generateFloatMatrix(Columns:Int, Rows:Int, RangeModifier:Float = 0.65):Array<Array<Float>>
{
//Blank 2D Array
var matrix:Array<Array<Float>> = InitFloatMatrix(Columns, Rows);
var range:Float = 1;
//Set Values for all four corners
matrix[0][0] = Math.random() * range;
matrix[Rows-1][0] = Math.random() * range;
matrix[0][Columns-1] = Math.random() * range;
matrix[Rows - 1][Columns - 1] = Math.random() * range;
//Calculates the amount of segments in base 2
var length = Math.sqrt((Columns * Columns) + (Rows * Rows));
var power:Int = Std.int(Math.pow(2, Math.ceil(Math.log(length) / Math.log(2))));
//Stores largest calculated value for normalization
var max:Float = 0;
var width:Int = Std.int(Columns);
var height:Int = Std.int(Rows);
var i:Int = 1;
while (i < power)
{
//Segment Size
width = Std.int(Columns / i);
height = Std.int(Rows / i);
for (y in 0...i)
{
for (x in 0...i)
{
//Top Left Coordinates per segment
var left = width * x;
var top = height * y;
//Find Midpoint
var xMid = Math.ceil(left + (width / 2));
var yMid = Math.ceil(top + (height / 2));
//Make sure right and bottom do not go out of bounds
var right:Int = (left + width < Columns ? left + width : Columns - 1);
var bottom:Int = (top + height < Rows ? top + height : Rows - 1);
//Sets midpoint value to average of all four corners.
matrix[yMid][xMid] =
(matrix[top][left] +
matrix[bottom][left] +
matrix[bottom][right] +
matrix[top][right]) / 4;
//trace ("Top: " + top + " - Left: " + left + " - Bottom: " + bottom + " - Right: " + right);
//Adds random value to midpoint
matrix[yMid][xMid] += Math.random() * range;
//Set side values to average of adjacent corners
matrix[top][xMid] = (matrix[top][left] + matrix[top][right]) / 2;
matrix[bottom][xMid] = (matrix[bottom][left] + matrix[bottom][right]) / 2;
matrix[yMid][left] = (matrix[top][left] + matrix[bottom][left]) / 2;
matrix[yMid][right] = (matrix[top][right] + matrix[bottom][right]) / 2;
max = Math.max(matrix[top][left], max);
}
}
//Reduces range
range *= RangeModifier;
i *= 2;
}
//Normalizes all values in matrix
for (y in 0...Rows)
{
for (x in 0...Columns)
{
matrix[y][x] /= max;
}
}
return matrix;
}
These are the images it is producing if I use each value to render each pixel to the specified coordinate. All the pixels that are rendered white have the value 0, black is value 1.
Your problem is that you don't necessarily hit the already populated pixels with your calculations if your map dimensions are not a power of two. For example if your map is 30 units wide, your grid width is 15 in the first pass and 7 in the second pass, where it bases its calculations on the yet untouched unit 14.
A solution is to do all calculations with floating-point arithmetic until you determine the unit indices, which must of course be integer:
while (i < power)
{
var width:Float = Columns / i; // Floating-point division
var height:Float = Rows / i;
for (y in 0...i)
{
for (x in 0...i)
{
var left:Int = Math.floor(width * x);
var top:Int = Math.floor(height * y);
var xMid:Int = Math.floor(width * (x + 0.5));
var yMid:Int = Math.floor(height * (y + 0.5));
var right:Int = Math.floor(width * (x +1));
var bottom:Int = Math.floor(height * (y + 1));
//Make sure right and bottom do not go out of bounds
if (right > Columns - 1) right = Columns - 1;
if (bottom > Rows - 1) bottom = Rows - 1;
// Do offset and interpolation stuff
}
}
}
This should give you a random map, graph-paper effect and all.
(Caveat: I'm not familiar with Haxe, but have tested this in Javascript, which doesn't have an integer type. I've used Math-floor throughout, where you'll want to do it the Haxe way.)
Finally, it looks to me that you do too many passes. I'd base the power on the maximum of the two dimensions instead of the diagonal. You can also skip the last step where wthe width is near one.

QGraphicsScene, Item Coordinates Affect Performance?

With the below code snippet I create a scene with 100.000 rectangles.
The performance is fine; the view responds with no delays.
QGraphicsScene * scene = new QGraphicsScene;
for (int y = -50000; y < 50000; y++) {
scene->addRect(0, y * 25, 40, 20);
}
...
view->setScene(scene);
And now the 2nd snippet sucks
for (int y = 0; y < 100000; y++) {
scene->addRect(0, y * 25, 40, 20);
}
For the 1st half of scene elements the view delays to respond on mouse and key events, and for the other half it seems to be ok ?!?
The former scene has sceneRect (x, y, w, h) = (0, -1250000, 40, 2499995).
The latter scene has sceneRect (x, y, w, h) = (0, 0, 40, 2499995).
I don't know why the sceneRect affects the performance, since the BSP index is based on relative item coordinates.
Am I missing something? I didn't find any information on the documentation,
plus the Qt demo 40000 Chips also distributes the elements around (0, 0), without explaining the reason for that choice.
// Populate scene
int xx = 0;
int nitems = 0;
for (int i = -11000; i < 11000; i += 110) {
++xx;
int yy = 0;
for (int j = -7000; j < 7000; j += 70) {
++yy;
qreal x = (i + 11000) / 22000.0;
qreal y = (j + 7000) / 14000.0;
...
I have a solution for you, but promise to not ask me why is this working,
because I really don't know :-)
QGraphicsScene * scene = new QGraphicsScene;
// Define a fake symetrical scene-rectangle
scene->setSceneRect(0, -(25*100000+20), 40, 2 * (25*100000+20) );
for (int y = 0; y < 100000; y++) {
scene->addRect(0, y * 25, 40, 20);
}
view->setScene(scene);
// Tell the view to display only the actual scene-objects area
view->setSceneRect(0, 0, 40, 25*100000+20);
For the common case, the default index
method BspTreeIndex works fine. If
your scene uses many animations and
you are experiencing slowness, you can
disable indexing by calling
setItemIndexMethod(NoIndex). Qt-doc
You will need to call setItemIndexMethod(QGraphicsScene::NoIndex) before insertion:
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
for (int y = 0; y < 100000; y++) {
scene->addRect(0, y * 25, 40, 20);
}
//...
It could be due to loss of precision with float. A 32 bit float has a 23 bit mantissa (or significand), 1 bit sign and 8 bit exponent. This is like scientific notation. You have 23 "significant digits" (really 24 due to an implicit leading 1) and an exponent of 2^exp where the exponent can range from -126 to 127 (others are used to give you things like NaN and Inf). So you can represent really large numbers like 2^24*2^127 but the next closest floating point number to such a float is (2^24-1)*2^127 or 170 billion billion billion billion away. If you try to add a smaller amount (like 1000) to such a number it doesn't change. It has no way to represent that.
This becomes significant in computer graphics because you need some of your significant digits left over to make a fractional part. When your scene ranges up to 1250000.0 you can add 0.1 to that and get 1250000.1. If you take 2500000.0 + 0.1 you get 2500000.0. The problem is magnified by any scaling or rotation that occurs. This can lead to obvious visual problems if you actually fly out to those coordinates and look at your scene.
Why does centering around 0 help? Because there's a separate sign bit in the floating point representation. In floating point there are "more numbers" between (-x,+x) than there are from (0,2x). If I'm right it would also work if you simply scaled your entire scene down by 1/2. This moves the most significant bit down leaving it free for precision on the other end.
Why would this lead to poor performance? I can only speculate without reading the Qt source, but consider a data structure for storing objects by location. What might you have to do differently if two objects touch (or overlap) due to loss of precision that you didn't have to do when they did not overlap?

Resources