How would I snap a position to a rectangular grid? - processing

I'm trying to make a midi-editor in processing and I need to have rectangular cells that you can click on to add a note there.
So far I've done googling but haven't found a result. What happens is when you click the further down the less accurate it gets.
I don't know what is going wrong and I've had this problem in the past but couldn't fix it.
Note: The cells are not square.

Example processing code to snap the mouse coordinates to the center of the nearest grid cell (where cell dimensions are defined by rectangle width and height).
int w = 48; // rectangle width
int h = 24; // rectangle height
int snapX = round(mouseX / w) * w + w/2; // '+ w/2' is offset to center of cell
int snapY = round(mouseY / h) * h + h/2; // '+ h/2' is offset to center of cell

Related

Processing - creating circles from current pixels

I'm using processing, and I'm trying to create a circle from the pixels i have on my display.
I managed to pull the pixels on screen and create a growing circle from them.
However i'm looking for something much more sophisticated, I want to make it seem as if the pixels on the display are moving from their current location and forming a turning circle or something like this.
This is what i have for now:
int c = 0;
int radius = 30;
allPixels = removeBlackP();
void draw {
loadPixels();
for (int alpha = 0; alpha < 360; alpha++)
{
float xf = 350 + radius*cos(alpha);
float yf = 350 + radius*sin(alpha);
int x = (int) xf;
int y = (int) yf;
if (radius > 200) {radius =30;break;}
if (c> allPixels.length) {c= 0;}
pixels[y*700 +x] = allPixels[c];
updatePixels();
}
radius++;
c++;
}
the function removeBlackP return an array with all the pixels except for the black ones.
This code works for me. There is an issue that the circle only has the numbers as int so it seems like some pixels inside the circle won't fill, i can live with that. I'm looking for something a bit more complex like I explained.
Thanks!
Fill all pixels of scanlines belonging to the circle. Using this approach, you will paint all places inside the circle. For every line calculate start coordinate (end one is symmetric). Pseudocode:
for y = center_y - radius; y <= center_y + radius; y++
dx = Sqrt(radius * radius - y * y)
for x = center_x - dx; x <= center_x + dx; x++
fill a[y, x]
When you find places for all pixels, you can make correlation between initial pixels places and calculated ones and move them step-by-step.
For example, if initial coordinates relative to center point for k-th pixel are (x0, y0) and final coordinates are (x1,y1), and you want to make M steps, moving pixel by spiral, calculate intermediate coordinates:
calc values once:
r0 = Sqrt(x0*x0 + y0*y0) //Math.Hypot if available
r1 = Sqrt(x1*x1 + y1*y1)
fi0 = Math.Atan2(y0, x0)
fi1 = Math.Atan2(y1, x1)
if fi1 < fi0 then
fi1 = fi1 + 2 * Pi;
for i = 1; i <=M ; i++
x = (r0 + i / M * (r1 - r0)) * Cos(fi0 + i / M * (fi1 - fi0))
y = (r0 + i / M * (r1 - r0)) * Sin(fi0 + i / M * (fi1 - fi0))
shift by center coordinates
The way you go about drawing circles in Processing looks a little convoluted.
The simplest way is to use the ellipse() function, no pixels involved though:
If you do need to draw an ellipse and use pixels, you can make use of PGraphics which is similar to using a separate buffer/"layer" to draw into using Processing drawing commands but it also has pixels[] you can access.
Let's say you want to draw a low-res pixel circle circle, you can create a small PGraphics, disable smoothing, draw the circle, then render the circle at a higher resolution. The only catch is these drawing commands must be placed within beginDraw()/endDraw() calls:
PGraphics buffer;
void setup(){
//disable sketch's aliasing
noSmooth();
buffer = createGraphics(25,25);
buffer.beginDraw();
//disable buffer's aliasing
buffer.noSmooth();
buffer.noFill();
buffer.stroke(255);
buffer.endDraw();
}
void draw(){
background(255);
//draw small circle
float circleSize = map(sin(frameCount * .01),-1.0,1.0,0.0,20.0);
buffer.beginDraw();
buffer.background(0);
buffer.ellipse(buffer.width / 2,buffer.height / 2, circleSize,circleSize);
buffer.endDraw();
//render small circle at higher resolution (blocky - no aliasing)
image(buffer,0,0,width,height);
}
If you want to manually draw a circle using pixels[] you are on the right using the polar to cartesian conversion formula (x = cos(angle) * radius, y = sin(angle) * radius).Even though it's focusing on drawing a radial gradient, you can find an example of drawing a circle(a lot actually) using pixels in this answer

How does depth work in a frustum environment?

I need some help understanding the basics of a frustum transformation. Mainly, how depth works.
The following uses a viewport of 768x1024. Using an Orthogonal projection and a square of 768x768 (z defaults to 0) with no translation or scaling, and a viewport of glViewport(0, 0, 768, 1024) this square easily fills the width of the frame:
Now when I change the project to a frustum and mess with the z translation, the square scales appropriately due to the perspective changes.
Here is the same square in such an environment:
I can play with this z translation, as well as the near and far parameters of the frustum matrix and make the square change is apparent onscreen size accordingly. Fine.
But what I cannot figure out is the obvious relationship between its onscreen size and these depth parameters.
For example, suppose I want to use a frustum but have the square fill the frame width, as in my first example image above. How to achieve this?
I would think that if the z translation matched the near plane, then you'd essentially have a square "right in front of the camera", filling the frame. But I cannot figure a way to achieve this. If my near is 1 and my z translation is -1, then the square should be sitting right on the near plane itself (right?!) , filling the width of the frame (where the frustum's left and right planes are the same as the orthogonal projection).
I could paste a bunch of code here to show what I'm doing but I think the concept here is clear. I just want to figure out where the near plane actually is, how to situate something on it, as this will help me understand how the frustum is working.
Okay here is the relevant code I'm using, where width=768 and height=1024.
My vertex shader is the simple gl_Position=Projection*Modelview*Position;
My projection matrix (frustum) is thus:
Frustum(-width/2, width/2, -height/2, height/2, 1,10);
This function is:
static Matrix4<T> Frustum(T left, T right, T bottom, T top, T near, T far)
{
T a = 2 * near / (right - left);
T b = 2 * near / (top - bottom);
T c = (right + left) / (right - left);
T d = (top + bottom) / (top - bottom);
T e = - (far + near) / (far - near);
T f = -2 * far * near / (far - near);
Matrix4 m;
m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;
return m;
}
My square is just two 2d triangles with a default z=0, and an x range from left as -768/2 and right edge at 768/2. The square is clearly working properly as my first image above shows, using the orthogonal projection. (Though I switched to the frustum projection for this question)
To draw the square, I translate the Modelview with:
Translate(0, 0, -1);
Using:
static Matrix4<T> Translate(T x, T y, T z)
{
Matrix4 m;
m.x.x = 1; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = 1; m.y.z = 0; m.y.w = 0;
m.z.x = 0; m.z.y = 0; m.z.z = 1; m.z.w = 0;
m.w.x = x; m.w.y = y; m.w.z = z; m.w.w = 1;
return m;
}
As you can see, the translation should put the square on the near plane, yet it looks like this:
If I translate instead of -1.01 just to be sure I avoid near clipping, the result is the same. If I do not translate, thus z=0, the square does not appear, as you'd expect, since it would be behind the camera.
In your frustum matrix, m.w.w should be 0, not 1. This will fix your problem.
But, the mistake isn't your fault. It's my fault! I'm actually the one who wrote that code in the first place, and unfortunately it has proliferated. It's an errata in my book (iPhone 3D Programming), which is where it first appeared.
Feeling very guilty about this!
If my near is 1 and my z translation is -1, then the square should be sitting right on the near plane itself (right?!)
Yes
, filling the width of the frame (where the frustum's left and right planes are the same as the orthogonal projection).
Not neccesarily. The near plane has the extents given with the left, right, bottom and top parameters of glFrustum. A rectangle going to exactly those bounds will snugly fit the viewport when being placed at the near plane distance.

How to change only width of path(rect, circle) while mouse drag using paper.js

I have stucked at resizing only width of an item in the canvas using paper.js
I have done in following ways to resize , but it results in resizing both left and right sides from the center of rectangle/circle.
function onMouseDrag(event){
(selectedItem.bounds.contains(event.point)) ?
selectedItem.scale(0.9871668311944719,1) : selectedItem.scale(1.013, 1);
}
above code resizes in both x-directions.
Help me to resize width only in one direction.
thanks,
suribabu.
You can center the scale operation at any point by using the form:
scale(hor, ver, point)
So in your case, if you want to scale from the left-center of your selected item, you could use:
function onMouseDrag(event){
(selectedItem.bounds.contains(event.point)) ?
selectedItem.scale(0.9871668311944719, 1, selectedItem.bounds.left) : selectedItem.scale(1.013, 1, selectedItem.bounds.left);
}
I am not sure what you mean with scale only the width. If you want to have thicker path than changing the strokeWidth instead might do what you want.
If you are wondering why the scaled path expands in both directions on the x-axis than you might check the location of the paths local center. If some nodes of the path have negative coordinates relative to this local center, scaling them with a positive value decreases their coordinates even more.
Perhaps you should normalize all the vertices, means move them directly so that the smallest x and y value of all vertices is 0.
Greetings and good luck
Try this:
function onMouseDown(e) {
var cx = e.point.x;
var cy = e.point.y;
var rectangle = new Rectangle(e.point, new Size(1,1));
path = new Path.Ellipse(rectangle);
path.strokeColor = 'red';
}
function onMouseDrag(e) {
path.remove();
var x = Math.min(e.point.x, cx),
y = Math.min(e.point.y, cy),
w = Math.abs(e.point.x -cx),
h = Math.abs(e.point.y -cy);
var rectangle = new Rectangle(x,y,w,h);
path = new Path.Ellipse(rectangle);
path.strokeColor = 'red'
}

how to account for linewidth in drawing lines within a bounding box

I am drawing a set of evenly spaced horizontal lines within the entirety of a bounding box.
The problem I am having is that the lines (when larger than 1px) get drawn beyond the top and bottom edges of my bounds. Half on each side of the top and bottom is missing, to be precise.
Here is some pseudo code that attempts a fix for this, but it didn't work. It should describe what I am trying to do:
var halfline = linewidth / 2.;
var maxheight = boxsize.height - halfline;
var minheight = halfline;
//draw h lines
for(i = 0; i < maxlines; i++)
{
var xloc = 0;
var xfrac = i / maxlines - 1;
var yloc = (xfrac * boxsize.height) + minheight;
move_to(xloc, yloc);
line_to(boxsize.width, yloc);
}
Please keep in mind that the lang is not important here, just the idea of how to offset and scale the lines (that are drawn within the for loop) properly.
Thanks for any tips... It's safe to assume the following:
the line width is in pixels
the coordinate system is pixel-based, from (0,0) to (n,n)
Your question is a little unclear, but I think this might help:
var availablespace = boxsize.height - linewidth;
...
var yloc = (xfrac * availablespace) + minheight;

How do I find a dimension of aspect ratio 4:3 which fits within a predetermined size?

The problem here is I have a display window of size x by y, and I need to display an image inside the window without any scrolling, and to maintain the aspect ratio of 4:3. I have the following snippet of code:
// Lock the current height, calculate new width of the canvas and scale the viewport.
// get width of the movie canvas
qreal width = canvas_->width();
// Find the height of the video
qreal height = (width/4.0) * 3;
// find original width and height for video to calculate scaling factor
qreal videoWidth = movieData_->GetWidth();
qreal videoHeight = movieData_->GetHeight();
// calculate scaling factor
qreal scaleFactorWidth = width/videoWidth;
qreal scaleFactorHeight = height/videoHeight;
Of course, by using either the height, or the width as the 'anchor', one way or other the new image will cause scrolling (assuming the original image is larger than the window in the first place). How do I find a dimension of aspect ratio 4:3 which fits within a predetermined size?
Edit
I would need to pass in a scale factor for both x and y to do the scaling
canvas_->scale(scaleFactorWidth, scaleFactorHeight);
Just take the minimum of the both calculated values:
scale = min(scaleFactorWidth, scaleFactorHeight)
or (if you want outer-fit)
scale = max(scaleFactorWidth, scaleFactorHeight)
struct dimensions resize_to_fit_in(struct dimensions a, struct dimensions b) {
double wf, hf, f;
struct dimensions out;
wf = (double) b.w / a.w;
hf = (double) b.h / a.h;
if (wf > hf)
f = hf;
else
f = wf;
out.w = a.w * f;
out.h = a.h * f;
return out;
}
An here is a C version where the returned dimension will be a dimension 'a' fitted in dimension 'b' without loosing aspect ratio.
Find the largest of the two values width, w and height h. Say your maximum width x height is 100 x 80. Note that 100/80 = 1.25.
Case 1: If w/h > 1.25, then divide w by 100 to get the ratio of your original size to the new size. Then multiply h by that ratio.
Case 2: Otherwise, then divide h by 80 to get the ratio of your original size to the new size. Then multiply w by that ratio.
Here's an ActionScript version of what you ask (resize while maintaining aspect ratio)... shouldn't be too hard to port to whatever:
private static function resizeTo(dispObj:DisplayObject, width:Number, height:Number) : void
{
var ar:Number = width / height;
var dispObjAr:Number = dispObj.width/dispObj.height;
if (ar < dispObjAr)
{
dispObj.width = width;
dispObj.height = width / dispObjAr;
}
else
{
dispObj.height = height;
dispObj.width = height * dispObjAr;
}
return;
}
EDIT: In order to maintain 4:3 the source images would need to be 4:3

Resources