Dividing rotated rectangle into equal area grid - javascript

I have a rotated rectangle that is represented by the coordinates of its 4 vertices (Actually represented by 4 lat-lon). I want to divide the rectangle into equal area grids.
I need this to find the approx area of intersection of 2 rotated rectangles, (using sampling approach).
How do I divide the rectangle into equal area grid ? I just want the center points of the grids. This is because I will check how many of these center points lie inside a 2nd rectangle and find the approx intersection area.
I tried searching, but most of the solution do not work for rotated rectangles.
Note : I am using JavaScript for implementation. Code will be helpful :)
Edit : This code is will NOT work for rotated rectangle.
var numDivide = 7;
var i = (region1[1].x - region1[0].x) / numDivide;
var j = (region1[2].y - region1[0].y) / numDivide;
var xPos = region1[0].x;
var yPos = region1[0].y;
var gridCenters = [];
for(var k = 0; k < numDivide; ++k)
{
var newPosX = (xPos + (i / 2));
for(var l = 0; l < numDivide; ++l)
{
var newPosY = (yPos + (j / 2));
gridCenters.push({x: newPosX, y: newPosY});
yPos = yPos + j;
}
xPos = xPos + i;
yPos = region1[0].y;
}

Related

How to move an ellipse along a line with multiple points?

I am currently doing up a mini project on the side as part of my beginner lesson to Javascript. I am hoping to allow an ellipse to appear along points on a few lines in a graph. The coordinates are derived from a css file, using the p5js library.
Following this example, I could only produce multiple ellipses (the amount corresponds to the number of points I have on the line). Is there any way I can somehow 'clear' the ellipses and allow only one to appear each time it travels on the lines?
Would also be great if there are any suggestions as to how I can make ellipses appear on exact coordinates when my mouse hovers over the lines at different points. I'm unable to use map() accurately.
The CSV has its heading with number of days in a month, first column with months and the remaining are data according to days in each month.
Below is a screenshot of what is currently happening, as well as a snippet the said code. Please do kindly correct me if my question wasn't well-asked. Thank you!
var endDay;
var beginX;
var beginY;
var beginY;
var endY;
var distX;
var distY;
var prevStart = null;
for (var i = 0; i < this.data.getRowCount(); i++) {
var a = this.data.getRow(i);
for(var k = 1; k < numDays; k++) {
currEnd = {
'day': this.firstDay + k - 1 ,
'case': a.getNum(k) //get no. of cases by day
}
if(prevStart != null) {
// this.mapDayToWidth, this.mapCaseToHeight are helpers to
// give scaled values
for plotting
beginX = this.mapDayToWidth(prevStart.day);
endX = this.mapDayToWidth(currEnd.day);
beginY = this.mapCaseToHeight(prevStart.case);
endY = this.mapCaseToHeight(currEnd.case);
let new_endX = constrain(mouseX, endX - 20, endX + 20);
distX = endX - beginX;
distY = endY - beginY;
x = beginX + pct * distX;
y = beginY + pct * distY;
pct += 0.00001;
}
prevStart = currEnd;
if(pct < 1.0) {
this.drawEllipses(mouseX, endY, 10);
}
}
}
// how the ellipse is drawn
this.drawEllipse = function(ellipseX, ellipseY, size, begin_X, end_X) {
fill('black');
ellipse(ellipseX, ellipseY, size);
};
// how the line graph was plotted
this.drawLines = function(colr, x1, y1, x2, y2) {
strokeWeight(2);
stroke(colr);
beginShape();
line(x1,
y1,
x2,
y2
);
endShape();
};

p5.js Nested For Loop not iterating

I am trying to create some scales measuring sound frequency for a music visualiser project. They are meant to display 4 different frequencies ( bass, lowMid, highMid and treble in a 2x2 grid pattern. I'm nearly there I have my rectangles but the needle which measures and shows the frequency itself is only iterating for the top row x and not the bottom row. I'm pretty new to JavaScript so I'm sure it could be something very simple that I'm missing.
// draw the plots to the screen
this.draw = function() {
//create an array amplitude values from the fft.
var spectrum = fourier.analyze();
//iterator for selecting frequency bin.
var currentBin = 0;
push();
fill('#f0f2d2');
//nested for loop to place plots in 2*2 grid.
for(var i = 0; i < this.plotsDown; i++) {
for(var j = 0; j < this.plotsAcross; j++) {
//calculate the size of the plots
var x = this.pad * j * 10;
var y = height/20 * i * 10;
var w = (width - this.pad) / this.plotsAcross;
var h = (height - this.pad) / this.plotsDown;
//draw a rectangle at that location and size
rect(x, y, w, h);
//add on the ticks
this.ticks((x + w/2), h, this.frequencyBins[i])
var energy = fourier.getEnergy(this.frequencyBins[currentBin]);
//add the needle
this.needle(energy, (x + w/2), h)
currentBin++;
}
}
pop();
};

How to calculate degree between two line with integer values (not vectors)

I'm working on small effect animation where it creates 5 distinctive objects expanding in 5 different directions from the center. The objects should not stack on each other so i'm thinking about distributing them in separated angles of circle but i don't know how to calculate the angle between two randomly created lengths of lines in px (for example: 100px line and 50px line)
Here is my code:
//Container of the objects
var box = $('.nodebox')
box.css({
height: box.width(),
top: (($(window).height() - box.width())/2),
})
//Main object in the center, one click on this, it will disappear followed by the activation of 5 sub-objects animation.
var Ndd = $('.Node');
Ndd.css({
top: ((box.width()-Ndd.width())/2),
left:((box.height()-Ndd.height())/2)
})
//Randomly creating the sub-objects
function createNnodes(n){
var nodeArrays = [];
for (var i = 0; i< n ; i++){
var smNd = $('<div class="smallNodes"></div>');
if (!$('body').data('mobile')){ //check to see if the device is mobile or not
var widthn = (Math.random()*($(window).width()*0.04) + $(window).width()*0.01);
} else {
var widthn = (Math.random()*($(window).width()*0.1) + $(window).width()*0.04);
};
var heightn = widthn; //making sure the objects are square-shaped
smNd.css({width: widthn, height: heightn})
nodeArray.push(smNd);
}
return nodeArrays;
}
//Handling the animation
function animateNodes(){
var nodeArray = createNnodes(6);
//creating 2 random distances for each object so that it tralvels diagonally or horizontally or vertically
for (var i = 0; i < nodeArray.length; i++){
var distance1 = ((Math.random()*Ndd.width()) + Ndd.width()*0.5);
var distance2 = ((Math.random()*Ndd.width()) + Ndd.width()*0.5);
//Create random "+" or "-"
function Pornot() {
if(Math.floor(Math.random()*2)){
return '+=';
}else {
return '-=';
}
}
var plusornot1 = Pornot();
var plusornot2 = Pornot();
$(nodeArray[i]).css({
top:((box.height()-$(nodeArray[i]).width())/2),
left:((box.width()-$(nodeArray[i]).width())/2)
}).appendTo('.nodebox').animate({
left: plusornot1 + distance1,
top: plusornot2 + distance2,
opacity:0,
},2000,function(){
$(nodeArray[i]).remove();
})
}
}
The code above works just fine, what my only concern is, again, how to specify the angle between distance1 and distance2...
A picture to demonstrate:
Click to view picture
Upon clicking on screen the main node will disappear. After that, 5 smaller instances of the node are created behind it and they synchronously move away from the center in 5 different angles.
Center point coordinates: (xc, yc)
First point coordinates: (x1, y1)
Second point coordinates: (x2, y2)
Angle between line segments (xc, yc)-(x1, y1) and (xc, yc)-(x2, y2):
dx1 = x1 - xc
dx2 = x2 - xc
dy1 = y1 - yc
dy2 = y2 - yc
len1 = Sqrt(dx1 * dx1 + dy1 * dy1)
len2 = Sqrt(dx2 * dx2 + dy2 * dy2)
Angle = ArcCos((dx1 * dx2 + dy1 * dy2) / (len1 * len2))

Paper.js: fastest way to draw many iterated shapes over loop

jsfiddle here: http://jsfiddle.net/yw0w18m3/2/
I'm using paper.js to make a background image that looks somthing like this:
Basically, I'm creating a couple thousand triangles over a loop and rotating them on every other iteration.
function Tri(x, y, rotate) {
var tri = new Path([
new Point((x - 42), (y - 48)),
new Point((x - 42), y),
new Point(x, (y - 24)),
new Point((x - 42), (y - 48))
]);
tri.fillColor = {
hue: Math.random() * 360,
saturation: 0,
brightness: ( (( Math.random() ) * .95) + .3 )
};
if(rotate) { tri.rotate(180); }
}
for (var i = 0; i < 2000; i++) {
rotate = false;
if( i % 2 ) {
rotate = true;
}
new Tri(x, y, rotate);
x = x + 42;
if( x > (winWidth + 42) ) {
x = 0 ;
y = y + 24;
}
}
There seems to be a brief 1-2 second pause/freeze though while the shapes are being drawn. Is there a more efficient way to draw all the shapes first (or push to an array) then add that to the canvas all at once?
I based my code off of the example here: http://paperjs.org/examples/candy-crash/ (click "source" in the upper right corner).
Any help is much appreciated.
Thanks!
I would end up creating two triangles, one rotated, so they don't have to be built from new points each time. Then choose the correct triangle based on the rotation variable and clone it, as opposed to create points and a triangle from scratch each time. Finally, just change the position of the cloned triangle.
Last, I would correct the maxTri so it doesn't do more than it needs to. The paren should follow the 48, not the 24. You're doing an order of magnitude more triangles than needed.
Here's a link to the sketch.paperjs.org solution I created based on your code. I find sketch easier to use than jsfiddle for paper examples.
proto1 = new Path([
new Point(0, -24),
new Point(0, 24),
new Point(42, 0)
]);
proto1.closed = true;
proto2 = proto1.clone();
proto2.rotate(180);
function putTriangle(pos, rotate) {
var tri = (rotate ? proto2 : proto1).clone();
tri.position = pos;
tri.position = tri.position.subtract([21, 0])
tri.fillColor = {
hue: Math.random() * 360,
saturation: 0,
brightness: Math.random() * 0.5 + 0.5
}
}
var tris = [],
x = 42,
y = 24,
rotate,
winWidth = paper.view.size.width,
winHeight = paper.view.size.height,
rows = (winHeight + 48) / 24,
cols = (winWidth + 42) / 42,
numTri = rows * cols,
numTriOrig = (winWidth + 42) / 42 * (winHeight + 48 / 24);
//console.log(numTri, numTriOrig);
x = 0;
y = 0;
for (var row = 0; row < rows; row++) {
rowrotate = row % 2;
for (var col = 0; col <= cols; col++) {
rotate = rowrotate ^ col % 2;
putTriangle([x,y], rotate);
x += 42;
}
x = 0;
y = y + 24;
}
Two thoughts:
I see you use rotate to transform you triangles into place. This is an expensive operation. You could replace the rotate with a less geometric & more arithmetic calculation of the triangles orientation.
Also, I see is that the fill color is being changed with each triangle and state changes (like fill) are modestly expensive. You could group all the similarly colored triangles and draw them in a single batch.

Javascript store array outside dynamic content and reuse if needed

I'm experimenting with some html 5 canvas and at a certain point I tried to update the canvas with new bars (rectangles).
Now the tricky part.
Lets say you have an array with 1800 items(numbers generated by a php request).
You also have an html 5 canvas with the width of 1163px.
Now you need to draw bars(rectangles) in the canvas, but the bars need to remain 2px wide and there must be a 1px margin between all bars.
So the PHP file always returns 1800 numbers (color codes from image) and you need to extract just enough numbers to fit the canvas width(with the margin included(bar+margin)).
The new array of numbers you extract cannot just be the first 100-200 numbers! It must contain the (first or second) and (last or last-1) number.
What I have tried so far
<script>
// 1800 numbers !!! ......... //
arr = [12,1,21,1,2,13,21,32,1,5,4,6,5,4,6,4,8,3,5,4,9,6,8,7,9,1,3,6,4,6,4,5,9,87,4,4,5];
c = getElementById('canvas');
ctx = c.getContex('2d');
var can = 360;
var spliter = 2;
var canWidth = c.width;
var numOfBars = arr.length;
var barwidth = 2;
var margin = 1;
// amount of bars that will fit in the canvas //
var maxbars = (canWidth / (barwidth + margin));
var offset = arr.length / maxbars;
for(var i = 0; i < arr.length; i++) {
if(arr[i] % offset){
ctx.fillStyle = "#000000";
ctx.fillRect(
this.margin + i * this.barwidth / numOfBars,
0,
barwidth + margin,
100
);
}
}
</script>
This does not seem to work how I need it to work.
Thanks in advance.
Maxbars must be an integer right? and same for offset.
After that offset is your step.
var maxbars = Math.floor(canWidth / (barwidth + margin));
var offset = Math.floor(arr.length / maxbars);
for(var i = 0; i < arr.length; i+=offset) {
var colorcode = arr[i];
// fill stuff
}

Categories

Resources