Place rectangles randomly but not within x radius in the center - javascript

How can I place rectangles with variable width and height, randomly in a stage but away from a circle in the center which has radius of x
Thanks in advance
EDIT
check my code so far
http://jsfiddle.net/chchrist/cAShH/1/

The three potential options I would follow are:
Generate random coordinates in [400,400] and then check that the distance from [200,200] is less than 50. If it is, fine; if not, start again.
Generate random polar coordinates (i.e., angle and distance), where the distance is greater than 50. Then convert these to Cartesian, centred around [200,200] and bounded to your area... The problem with this approach is that it would introduce bias at the extremities of your rectangular area.
Ignore the circle and bound it by a square, then use the first approach but with simplified logic.

One approach might be to think about how to map uniform random numbers into legal positions.
For example (simplifying slightly), if you had a 200 x 200 square, and you wanted to avoid any points in a 100x100 square in the middle, you could do the following for each coordinate. Generate a random number between 0 and 100. If it's less than 50, use it directly; otherwise add 100 to it (to put it in the 150-200 range)
Conceptually this stretches the range around the "hole" in the middle, while still leaving the resulting points uniformly distributed.
It'll be trickier with your circle, as the axes are not independent, but a variation on this method could be worth considering. (Especially if you only have "soft" requirements for randomness and so can relax the constraints on the distribution somewhat).

I would start with a coordinate system centered at 0,0 and after you have generated valid coordinates map them onto your square/rectangle.
Here's a simple example:
function getValidCoordinates() {
var x, y, isValid = false;
while (!isValid) {
x = Math.random() * 400 - 200;
y = Math.random() * 400 - 200;
if (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) > 50)
isValid = true;
//else alert('too close ' + x + ',' + y);
}
return {x: x + 200, y: y + 200};
}
for (var i=0; i < 10; i++) {
var co = getValidCoordinates();
alert('x=' + co.x + ', y=' + co.y);
}

Related

Calculating the coordinates of a point on circle, along a line between the center of the circle and another point outside it?

Here's an image to demonstrate the question:
Let's say I have Point A at [0,0], and Point B at [50, 30]. I want to find the coordinates of Point X, along a circle of radius 15, with an origin at Point A, which is also on a line between Point A and Point B.
Pointers on the best method to do this?
Since this has been tagged JavaScript, here's a simple implementation:
// disclaimer: code written in browser
function Point2D(x, y) {
this.x = x;
this.y = y;
}
function findCircleInteresction(center, radius, target) {
var vector = new Point2D(target.x - center.x, target.y - target.y);
var length = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2));
var normal = new Point2D(vector.x / length, vector.y / length);
var result = new Point2D(center.x + (normal.x * radius), center.y + (normal.y * radius));
return result;
}
findCircleInteresction(new Point2D(0, 0), 15, new Point2D(50, 30));
Point2D is just a class to make objects with x and y properties.
findCircleInteresction takes three parameters:
- center the center of the circle
- radius the radius of the circle
- target a point outside the circle
In findCircleInteresction:
- calculate the vector between the center and the target
- get the length of the resulting vector
- compute the normal (normalized) of the vector
- find the point where the vector intersects with the circle by adding the center of the circle plus the normalized vector components multiplied by the radius of the circle
This code could be heavily optimized and it's untested but I think it illustrated the idea.
You would want to think of this as two overlapping triangles, one with sides Bx-Ax and By-Ay. What you want is to find the coordinates of X, which would specifically be a triangle with sides Xx-Ax and Xy-Ay but with known hypotenuse R, which is your radius of the circle. Notice that the angle for both triangles are equal in respect to the x-coordinates-axis.
So to get the angle of the triangle, take the arctan(By-Ay/Bx-Ax) Now with that angle, call it T, you can solve for the smaller legs with your know radius R.
To get the x coordinate you would take Rcos(T)
To get the y coordinate you would take Rsin(T)
Bringing it all together you have that Xx = Rcos(T) and Xy = Rsin(T)
If you are not willing to use a Math library, which this method would use, you can use ratio's (as Pointy commented)

How can I make a tetradecagon with Processing.Js?

I want to make a Tetradecagon, a polygon with 14 sides, with Processing.JS.
(I want to make the Tetradecagon like the one shown in the Image below!)
Using the numbers given in the image, which I would like to replicate, I concluded that each piece (I don't know it's proper name), has an angle of 25.714285714°.....25 and 10/14 = 25 and 5/7 - 5/7 in decimal form = 0.714285714So, I arrived at 25.714285714°
Now, in Processing.JS, I was wanting to use a while loop:
var r = 0;
var draw = function() {
translate(200,200);
while(r < 361){
rotate(r);
r = r + 25.714285714;
line(200,0,200,200);
}
};
Here, I have set one variable, r. r will be the variable for the rotate() function. The while loop will keep going until r meets 360 - this will allow for the the change in r, the angle, to increase by 25.714285714°, while r < 361.
But, sadly, this is not happening. What I see on my canvas is the line being shot off the screen.
(edit) I added translate(200,200); just above the while() loop - this helped, but the lines are still not looking like the picture above.
The second point of the line is not staying in the center; the whole line is being shifted. I only want the first (top) point to be shifted by the given change in angles.
How do I change the code in order to achieve the goal that I am striving for? Any help would be appreciated - Thanks for your time!
P.S. This is my result with the current code -
Processing.js is just for running Processing code. This looks like a mix of Processing and Javascript code so my first advice would be "write real Processing code".
With that said, if you want to do this based on coordinate rotation, look at your 14-gon: it's 14 repeated triangles, so analyze one triangle and draw that 14 times. Any triangular slice is defined by a line from "the center" to "a vertex on the 14-gon" at a (necessary) distance r, the radius of the circumscribing circle. So, given a vertex (r,0) on the 14-gon where is the next vertex (nx,ny)?
Simple maths:
first vertex = (x, y) = (r,0)
next vertex = (nx,ny) = (r,0) rotated over (0,0) by (phi = tau/14)
(I'm using tau here because it's a far more convenient constant for programming purposes. It's simply equal to 2*pi, and as such represents an entire circle, rather than a half circle)
Now, computing that rotate coordinate using basic trigonometry:
nx = r * cos(phi) - 0 * sin(phi) = r * cos(phi)
ny = r * sin(phi) + 0 * cos(phi) = r * sin(phi)
Alright, done. And this nx,ny computation is clearly not specific to the number 14, it about arbitrary angles, so let's code the solution and make it work for any n-sided polygon:
void setup() {
size(400,400);
noLoop();
}
void draw() {
background(255);
// offset the coordinate system so that (0,0) is the sketch center
translate(width/2,height/2);
// then draw a polygon. In this case, radius width/2, and 14 sided
drawNgon(width/2, 14);
}
void drawNgon(float r, float n) {
// to draw (r,0)-(x',y') we need x' and y':
float phi = TAU/n;
float nx = r * cos(phi);
float ny = r * sin(phi);
// and then we just draw that line as many times as there are sides
for(int a=0; a<n; a++) {
// draw line...
line(r,0, nx,ny);
// rotate the entire coordinate system...
rotate(phi);
// repeat until done.
}
}
And now we can freely change both the polygon radius and the number of sides by changing the input to drawNgon(..., ...).

Particles "run away" from mouse

Im creating a simple particle experiment on canvas. Now i want them to "run away" from mouse coursor over canvas. detecting the distance from the mouse is not a problem, but how to code their behaviour?
each particle is created as following:
var particle = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height),
xVel: Math.random() * 10 - 5,
yVel: Math.random() * 10 - 5,
}
so i assume i should also save the direction somehow, and if the distance from pointer is < x, reverse the direction? maybe also save old speed, and decrease it slowly while moving away?
how to detect the direction?
Velocity (xVel, yVel, together) is a 2D vector. And so is the distance between the mouse and the particles. A vector contains both direction and magnitude. So you want a vector that is the difference between the mouse position and the particle position.
var posRelativeToMouse = {
x: particle.x - mousPosX,
y: particle.y - mousPosY
};
So small numbers of x and y mean the the particle is close to the mouse, and big mean it's far away.
Next we need to figure out how these numbers should affect the velocity of the particle. So we need 2 things.
What direction do we push them in?
We already have this, mostly. posRelativeToMouse is a vector that has the direction we want. We just normalize it, which means to set the length of the vector to 1. To do that, we divide each component by the current length of the vector. The length of this vector is always the distance to from the particle to the mouse.
var distance = Math.sqrt(
posRelativeToMouse.x * posRelativeToMouse.x +
posRelativeToMouse.y * posRelativeToMouse.y
);
var forceDirection = {
x: posRelativeToMouse.x / distance,
y: posRelativeToMouse.y / distance,
};
How hard do we push the particles?
This is an inverse of the distance. Close means a big push, far means a little push. So lets reuse our distance we calculated above.
// distance past which the force is zero
var maxDistance = 1000;
// convert (0...maxDistance) range into a (1...0).
// Close is near 1, far is near 0
// for example:
// 250 => 0.75
// 100 => 0.9
// 10 => 0.99
var force = (maxDistance - distance) / maxDistance;
// if we went below zero, set it to zero.
if (force < 0) force = 0;
Ok we have a direction, and we have the force. All that's left is to apply this to the particle velocity.
particle.xVel += forceDirection.x * force * timeElapsedSinceLastFrame;
particle.yVel += forceDirection.y * force * timeElapsedSinceLastFrame;
And assuming you are animating your position each frame by that xVel/yVel, you should now have particles being pushed away by the mouse.
you can obtain a vector v by subtracting the position of particle from position of mouse,
then you can find the magnitude of this vector my taking sqrt(x^2 + y^2)
by dividing v by magnitude, you obtain a unit vector in the direction you want your particles to go.
for instance.
suppose I have 10 particles in a list U, each has an x and y field.
I can obtain it's vector from each particle v by setting v = (xpart - mousepart, ypart - mousepart)
then you need to find the magnitude vmag by taking sqrt(vx^2 + vy^2)
then you obtain vunit = (vx / vmag, vy / vmag)
This is the vector "away from the mouse".
the rest can be left to detemining speed you want to move at, and ensuring you bounce of walls and such.
I have a similar project at github open source:
https://github.com/dmitrymakhnin/JavaParticleSystem/blob/master/Main.java

Finding point n% away from the centre of a semicircle in Javascript?

I'm sorry to say that Math really isn't my strong suit. Normally I can get by, but this has got me totally stumped.
I'm trying to code up a quiz results screen in HTML/CSS/Javascript.
On my interface, I have a semicircle (the right hemisphere of a target).
I have a range of 'scores' (integers out of 100 - so 50, 80, 90 etc.).
I need to plot these points on the semicircle to be n% away from the centre, where n is the value of each score - the higher the score, the closer to the centre of the target the point will appear.
I know how wide my semicircle is, and have already handled the conversion of the % values so that the higher ones appear closer to the centre while the lower ones appear further out.
What I can't wrap my head around is plotting these points on a line that travels out from the centre point (x = 0, y = target height/2) of the target at a random angle (so the points don't overlap).
Any suggestions are gratefully received!
Do you have an example of what you want this to look like? It sounds like you want to divide up the circle into N slices where N is the number of points you need to display, then plot the points along each of those radii. So you might have something like:
Edit: code was rotating about the origin, not the circle specified
var scores = [];
//...
//assume scores is an array of distances from the center of the circle
var points = [];
var interval = 2 * Math.PI / N;
var angle;
for (var i = 0; i < N; i++) {
angle = interval * i;
//assume (cx, cy) are the coordinates of the center of your circle
points.push({
x: scores[i] * Math.cos(angle) + cx,
y: scores[i] * Math.sin(angle) + cy
});
}
Then you can plot points however you see fit.
After much headscratching, I managed to arrive at this solution (with the help of a colleague who's much, much better at this kind of thing than me):
(arr_result is an array containing IDs and scores - scores are percentages of 100)
for (var i = 0; i < arr_result.length; i++){
var angle = angleArray[i]; // this is an array of angles (randomised) - points around the edge of the semicircle
var radius = 150; // width of the semicircle
var deadZone = 25 // to make matters complicated, the circle has a 'dead zone' in the centre which we want to discount
var maxScore = 100
var score = parseInt(arr_result[i]['score'], 10)
var alpha = angle * Math.PI
var distance = (maxScore-score)/maxScore*(radius-deadZone) + deadZone
var x = distance * Math.sin(alpha)
var y = radius + distance * Math.cos(alpha)
$('#marker_' + arr_result[i]['id'], templateCode).css({ // target a specific marker and move it using jQuery
'left' : pointX,
'top': pointY
});
}
I've omitted the code for generating the array of angles and randomising that array - that's only needed for presentational purposes so the markers don't overlap.
I also do some weird things with the co-ordinates before I move the markers (again, this has been omitted) as I want the point to be at the bottom-centre of the marker rather than the top-left.

Raphael SVG VML Implement Multi Pivot Points for Rotation

Over the last two days I've effectively figured out how NOT to rotate Raphael Elements.
Basically I am trying to implement a multiple pivot points on element to rotate it by mouse.
When a user enters rotation mode 5 pivots are created. One for each corner of the bounding box and one in the center of the box.
When the mouse is down and moving it is simple enough to rotate around the pivot using Raphael elements.rotate(degrees, x, y) and calculating the degrees based on the mouse positions and atan2 to the pivot point.
The problem arises after I've rotated the element, bbox, and the other pivots. There x,y position in the same only there viewport is different.
In an SVG enabled browser I can create new pivot points based on matrixTransformation and getCTM. However after creating the first set of new pivots, every rotation after the pivots get further away from the transformed bbox due to rounding errors.
The above is not even an option in IE since in is VML based and cannot account for transformation.
Is the only effective way to implement
element rotation is by using rotate
absolute or rotating around the center
of the bounding box?
Is it possible at all the create multi
pivot points for an object and update
them after mouseup to remain in the
corners and center of the transformed
bbox?
UPDATE:
I've attempted to use jQuery offset to find the pivot after it's been rotated, and to use that offset location as the pivot point.
Demo site ...
http://weather.speedfetishperformance.com/dev/raphael/rotation.html
The best cross-browser way I can think of to do what you want is to implement the rotation yourself rather than let SVG do it. Rotating x,y coordinates is fairly simple and I've been using this (tcl) code whenever I need to do 2D rotation: Canvas Rotation.
The upside to this is you have maximum control of the rotation since you're doing it manually. This solves the problems you're having trying to guess the final coordinates after rotation. Also, this should be cross browser compatible.
The downside is you have to use paths. So no rects (though it should be easy to convert them to paths) or ellipses (a little bit harder to convert to path but doable). Also, since you're doing it manually, it should be slower than letting SVG do it for you.
Here's a partial implementation of that Tcl code in javascript:
first we need a regexp to tokenize SVG paths:
var svg_path_regexp = (function(){
var number = '-?[0-9.]+';
var comma = '\s*[, \t]\s*';
var space = '\s+';
var xy = number + comma + number;
var standard_paths = '[mlcsqt]';
var horiz_vert = '[hv]\s*' + number;
var arc = 'a\s*' + xy + space + number + space + xy + space + xy;
var OR = '\s*|';
return new RegExp(
standard_paths +OR+
xy +OR+
horiz_vert +OR+
arc,
'ig'
);
})();
now we can implement the rotate function:
function rotate_SVG_path (path, Ox, Oy, angle) {
angle = angle * Math.atan(1) * 4 / 180.0; // degrees to radians
var tokens = path.match(svg_path_regexp);
for (var i=0; i<tokens.length; i++) {
var token = tokens[i].replace(/^\s+|\s+$/g,''); // trim string
if (token.match(/\d/)) { // assume it's a coordinate
var xy = token.split(/[, \t]+/);
var x = parseFloat(xy[0]);
var y = parseFloat(xy[1]);
x = x - Ox; // Shift to origin
y = y - Oy;
var xx = x * Math.cos(angle) - y * Math.sin(angle); // Rotate
var yy = x * Math.sin(angle) + y * Math.cos(angle);
x = xx + Ox; // Shift back
y = yy + Oy;
token = x + ',' + y;
}
else if (token.match(/^[hv]/)) {
// handle horizontal/vertical line here
}
else if (token.match(/^a/)) {
// handle arcs here
}
tokens[i] = token;
}
return tokens.join('');
}
The above rotate function implements everything except horizontal/vertical lines (you need to keep track of previous xy value) and arcs. Neither should be too hard to implement.

Categories