(MATH ISSUE) Creating a SPIRAL out of points: How do I change "relative" position to absolute position - path

Recently I had the idea to make a pendulum out of points using Processing, and with a little learning I solved it easily:
int contador = 0;
int curvatura = 2;
float pendulo;
void setup(){
size(300,300);
}
void draw(){
background(100);
contador = (contador + 1) % 360; //"CONTADOR" GOES FROM 0 TO 359
pendulo = sin(radians(contador))*curvatura; //"PENDULO" EQUALS THE SIN OF CONTADOR, SO IT GOES FROM 1 TO -1 REPEATEDLY, THEN IS MULTIPLIED TO EMPHASIZE OR REDUCE THE CURVATURE OF THE LINE.
tallo(width/2,height/3);
println(pendulo);
}
void tallo (int x, int y){ //THE FUNTION TO DRAW THE DOTTED LINE
pushMatrix();
translate(x,y);
float _y = 0.0;
for(int i = 0; i < 25; i++){ //CREATES THE POINTS SEQUENCE.
ellipse(0,0,5,5);
_y+=5;
rotate(radians(pendulo)); //ROTATE THEM ON EACH ITERATION, THIS MAKES THE SPIRAL.
}
popMatrix();
}
So, in a brief, what I did was a function that changed every point position with the rotate fuction, and then I just had to draw the ellipses in the origin coordinates as that is the real thing that changes position and creates the pendulum ilussion.
[capture example, I just need 2 more points if you are so gentile :)]
[capture example]
[capture example]
Everything was OK that far. The problem appeared when I tried to replace the ellipses for a path made of vertices. The problem is obvious: the path is never (visually) made because all vertices would be 0,0 as they move along with the zero coordinates.
So, in order to make the path possible, I need the absolute values for each vertex; and there's the question: How do I get them?
What I know I have to do is to remove the transform functions, create the variables for the X and Y position and update them inside the for, but then what? That's why I cleared this is a maths issue, which operation I have to add in the X and Y variables in order to make the path and its curvature possible?
void tallo (int x, int y){
pushMatrix();
translate(x,y);
//NOW WE START WITH THE CHANGES. LET'S DECLARE THE VARIABLES FOR THE COORDINATES
float _x = 0.0;
float _y = 0.0;
beginShape();
for(int i = 0; i < 25; i++){ //CREATES THE DOTS.
vertex(_x,_y); //CHANGING TO VERTICES AND CALLING THE NEW VARIABLES, OK.
//rotate(radians(pendulo)); <--- HERE IS MY PROBLEM. HOW DO I CONVERT THIS INTO X AND Y COORDINATES?
//_x = _x + ????;
_y = _y + 5 /* + ???? */;
}
endShape();
popMatrix();
}
We need to have in mind that pendulo's x and y values changes in each iteration of the for, it doesn't has to add the same quantity each time. The addition must be progressive. Otherwise, we would see a straight line rotating instead of a curve accentuating its curvature (if you increase curvatura's value to a number greater than 20, you will notice the spiral)
So, rotating the coordinates was a great solution to it, now it's kind of a muddle to think the mathematical solution to the x and y coordinates for the spiral, my secondary's knowledges aren't enough. I know I have to create another variable inside the for in order to do this progression, but what operation should it have?
I would be really glad to know, maths

You could use simple trigonometry. You know the angle and the hypotenuse, so you use cos to get the relative x position, and sin to the y. The position would be relative to the central point.
But before i explain in detail and draw some explanations, let me propose another solution: PVectors
void setup() {
size(400,400);
frameRate(60);
center = new PVector(width/2, height/3); //defined here because width and height only are set after size()
}
void draw() {
background(255);
fill(0);
stroke(0);
angle = arc_magn*sin( (float) frameCount/60 );
draw_pendulum( center );
}
PVector center;
float angle = 0;
float arc_magn = HALF_PI;
float wire_length = 150;
float rotation_angle = PI/20 /60 ; //we divide it by 60 so the first part is the rotation in one second
void draw_pendulum(PVector origin){
PVector temp_vect = PVector.fromAngle( angle + HALF_PI);
temp_vect.setMag(wire_length);
PVector final_pos = new PVector(origin.x+temp_vect.x, origin.y+temp_vect.y );
ellipse( final_pos.x, final_pos.y, 40, 40);
line(origin.x, origin.y, final_pos.x, final_pos.y);
}
You use PVector class static method fromAngle( float angle ) that returns a unity vector of the given angle, then use .setMag() to define it's length.
Those PVector methods will take care of the trigonometry for you.
If you still want to know the math behind it, i can make another example.

Related

How to draw on the fly 2D pixel-by-pixel in MonoGame/XNA?

I was wondering how to draw on the fly pixel by pixel in XNA/MonoGame and could only find this. Problem is, the question wasn't centered about how to actually draw pixel by pixel but rather manage resources and updating stuff.
Because I couldn't find any simple and short answer and was wondering how to do for some time now, I'll share a snippet I stumbled upon (see answer).
NB: If anyone having a better approach or an alternative method to do it, feel free to post or comment!
You need to use the SetData() method of a Texture2D object you previously initialized with a 1 by 1 size.
Texture2D pixel; //ie. in class declaration
And later, for instance in the Initialize method:
pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new Color[] {Color.White});
Edit:
As Strom mentionned in his answer, the Texture2D object must be declared at the class level. You should avoid declaring or modifying a texture in the Draw() method as it'll slow the game loop.
Declare a class level variable for your texture and sizes:
Texture2D Tex, Tex1, Tex2;
const int WIDTH = 32;
const int HEIGHT = 32;
Color[] TexSource = new Color[WIDTH * HEIGHT];
Initialize the variables in LoadContent()
int radius = 5;
point center = new Point(WIDTH >> 2, HEIGHT >> 2);
Tex = new Texture2D(GraphicsDevice, WIDTH, HEIGHT);
for(int x = 0 ; x < WIDTH; x++)
for(int y = 0 ; y < HEIGHT; y++)
if(Math.Sqrt((x - center.x)* (x - center.x)) < radius && Math.Sqrt((y - center.y) * (y - center.y) < radius))
TexSource[x + y * WIDTH] = Color.Red;
else
TexSource[x + y * WIDTH] = Color.White;
Tex = SetData<Color>(TexSource);
//The resulting texture is a red circle on a white background.
//If you want to draw on top of an existing texture Tex1 as Tex2:
Tex1 = Content.Load<Texture2D>(Tex1Name);
Tex2 = new Texture2D(GraphicsDevice, Tex1.Width, Tex1.Height);
TexSource = Tex1.GetData<Color>();
// Draw a white \ on the image, we will assume tex1 is square for this task
for(int x = 0 ; x < Tex1.Width; x++)
for(int y = 0 ; y < Tex1.Width; y++)
if(x==y) TexSource[x + y * Tex1.Width] = Color.White;
You may change the textures in Update()
But, never create or modify a texture in Draw() ever.
The SpriteBatch.Draw() call expects the GraphicsDevice buffer to contain all of the texture data (by extension to the GPU buffer), any changes still happening(from Update and IsRunningSlowly == true) at this point will cause tearing when rendered.
The workaround of GraphicsDevice.Textures[0] = null; blocks the Draw call and the game until transfer to the GPU is complete, thus slowing the entire game loop.

How to calculate camera ray position for use with XMVector3Unproject(), DirectX11?

I'm trying to create a ray-casting camera in DirectX11 using XMVector3Unproject(). From my understanding, I will be passing in the (Vector3)position of the pixel on the near plane, and in separate call, a corresponding position on the far plane. Then I would subtract these vectors to get the direction of the ray. The origin would then be the Unprojected coordinate on the near plane. My problem here is calculating the origin of the ray to be passed in.
Example
// assuming screenHeight and screenWidth are the number of pixels.
const uint32_t screenHeight = 768;
const uint32_t screenWidth = 1024;
struct Ray
{
XMFLOAT3 origin;
XMFLOAT3 direction;
};
Ray rays[screenWidth * screenHeight];
for (uint32_t i = 0; i < screenHeight; ++i)
{
for (uint32_t j = 0; j < screenWidth; ++j)
{
// 1. ***calculate and store the current pixel position on the near plane***
// 2. ***calculate the corresponding point on the far plane***
// 3. ***pass both positions separately into XMVector3Unproject() (2 total calls to the function)***
// 4. ***store the returned vectors' difference into rays[i * screenWidth + j].direction***
// 5. ***store the near plane pixel position's returned vector into rays[i * screenWidth + j].origin***
}
}
Hopefully I'm understanding this correctly. Any help in determining the ray origins, or corrections would be greatly appreciated.
According to the documentation, the XMVector3Unproject function gives you the coordinates of a ray you have provided in camera space (Normalized-device coordinates), in object space (given your model matrix).
To generate your camera rays, you consider your camera pinhole (all the light passes through one point, which is your camera (0, 0, 0), then you choose your ray direction. Let say you want to generate W*H camera rays, your loop might look like this
Vector3 ray_origin = Vector3(0, 0, 0);
for (float x = -1.f; x <= 1.f; x += 2.f / W) {
for (float y = -1.f; y <= 1.f; y += 2.f / H) {
Vector3 ray_direction = Normalize(Vector3(x, y, -1.f)) - ray_origin;
Vector3 ray_in_model = Unproject(ray_direction, 0.f, 0.f,
width, height, znear, zfar,
proj, view, model);
}
}
You might also want to have a look at this link which sounds interesting

Make object move in a circle

I'm a beginner at programming, and I've been trying to make an object orbit around another object (or just move in a circle). But I haven't succeeded very well. Any ideas?
You need some constants to specify radius and speed:
const float speed = 100.0f;
const float radius = 50.0f;
you also need some variable to store angle:
float angle;
- (void)updateObject:(NSTimeInterval)dt
{
angle += speed * dt;
angle = fmodf(angle, 360.0f);
float x = cosf(DEGREES_TO_RADIANS(angle)) * radius;
float y = sinf(DEGREES_TO_RADIANS(angle)) * radius;
float newXPosition = _yourSprite.position.x + x;
float newYPosition = _yourSprite.position.y + y;
//Assign the values to your sprite
_yourSprite.position = ...
}
Try connecting two nodes with SKPhysicsJointLimit, with the first node not movable (maybe not dynamic), set the linear damping of the second node to zero and disable gravitation forces on it. It also should not collide with any other object, of course.When the joint is stretched to its maximum and you apply an Impulse vertical to the connection between the two objects, the object should start orbiting around the other one.
I have not tested this one.

RotatedRect ROI in OpenCV

I have a RotatedRect, I want to do some image processing in the rotated region (say extract the color histogram). How can I get the ROI? I mean get the region(pixels) so that I can do processing.
I find this, but it changes the region by using getRotationMatrix2D and warpAffine, so it doesn't work for my situation (I need to process the original image pixels).
Then I find this suggests using mask, which sounds reasonable, but can anyone teach me how to get the mask as the green RotatedRect below.
Excepts the mask, is there any other solutions ?
Thanks for any hint
Here is my solution, using mask:
The idea is construct a Mat mask by assigning 255 to my RotatedRect ROI.
How to know which point is in ROI (which should be assign to 255)?
I use the following function isInROI to address the problem.
/** decide whether point p is in the ROI.
*** The ROI is a rotated rectange whose 4 corners are stored in roi[]
**/
bool isInROI(Point p, Point2f roi[])
{
double pro[4];
for(int i=0; i<4; ++i)
{
pro[i] = computeProduct(p, roi[i], roi[(i+1)%4]);
}
if(pro[0]*pro[2]<0 && pro[1]*pro[3]<0)
{
return true;
}
return false;
}
/** function pro = kx-y+j, take two points a and b,
*** compute the line argument k and j, then return the pro value
*** so that can be used to determine whether the point p is on the left or right
*** of the line ab
**/
double computeProduct(Point p, Point2f a, Point2f b)
{
double k = (a.y-b.y) / (a.x-b.x);
double j = a.y - k*a.x;
return k*p.x - p.y + j;
}
How to construct the mask?
Using the following code.
Mat mask = Mat(image.size(), CV_8U, Scalar(0));
for(int i=0; i<image.rows; ++i)
{
for(int j=0; j<image.cols; ++j)
{
Point p = Point(j,i); // pay attention to the cordination
if(isInROI(p,vertices))
{
mask.at<uchar>(i,j) = 255;
}
}
}
Done,
vancexu
I found the following post very useful to do the same.
http://answers.opencv.org/question/497/extract-a-rotatedrect-area/
The only caveats are that (a) the "angle" here is assumed to be a rotation about the center of the entire image (not the bounding box) and (b) in the last line below (I think) "rect.center" needs to be transformed to the rotated image (by applying the rotation-matrix).
// rect is the RotatedRect
RotatedRect rect;
// matrices we'll use
Mat M, rotated, cropped;
// get angle and size from the bounding box
float angle = rect.angle;
Size rect_size = rect.size;
// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
if (rect.angle < -45.) {
angle += 90.0;
swap(rect_size.width, rect_size.height);
}
// get the rotation matrix
M = getRotationMatrix2D(rect.center, angle, 1.0);
// perform the affine transformation
warpAffine(src, rotated, M, src.size(), INTER_CUBIC);
// crop the resulting image
getRectSubPix(rotated, rect_size, rect.center, cropped);
If you need a superfast solution, I suggest:
crop a Rect enclosing your RotatedRect rr.
rotate+translate back the cropped image so that the RotatedRect is now equivalent to a Rect. (using warpAffine on the product of the rotation and the translation 3x3 matrices)
Keep that roi of the rotated-back image (roi=Rect(Point(0,0), rr.size())).
It is a bit time-consuming to write though as you need to calculate the combined affine transform.
If you don't care about the speed and want to create a fast prototype for any shape of the region, you can use an openCV function pointPolygonTest() that returns a positive value if the point inside:
double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)
Simple code:
vector<Point2f> contour(4);
contour[0] = Point2f(-10, -10);
contour[1] = Point2f(-10, 10);
contour[2] = Point2f(10, 10);
contour[3] = Point2f(10, -10);
Point2f pt = Point2f(11, 11);
an double res = pointPolygonTest(contour, pt, false);
if (res>0)
cout<<"inside"<<endl;
else
cout<<"outside"<<endl;

How to move 2 xna sprites away from eachother dynamically?

I have two items, lets call them Obj1 and Obj2... Both have a current position pos1 and pos2.. Moreover they have current velocity vectors speed1 and speed2 ... How can I make sure that if their distances are getting closer (with checking current and NEXT distance), they will move farther away from eachother ?
I have a signed angle function that gives me the signed angle between 2 vectors.. How can I utilize it to check how much should I rotate the speed1 and speed2 to move those sprites from eachother ?
public float signedAngle(Vector2 v1, Vector2 v2)
{
float perpDot = v1.X * v2.Y - v1.Y * v2.X;
return (float)Math.Atan2(perpDot, Vector2.Dot(v1, v2));
}
I check the NEXT and CURRENT distances like that :
float currentDistance = Vector2.Distance(s1.position, s2.position);
Vector2 obj2_nextpos = s2.position + s2.speed + s2.drag;
Vector2 obj1_nextpos = s1.position + s1.speed + s1.drag;
Vector2 s2us = s2.speed;
s2us.Normalize();
Vector2 s1us = s1.speed;
s1us.Normalize();
float nextDistance = Vector2.Distance(obj1_nextpos , obj2_nextpos );
Then depending whether they are getting bigger or smaller I want to move them away (either by increasing their current speed at the same direction or MAKING THEM FURTHER WHICH I FAIL)...
if (nextDistance < currentDistance )
{
float angle = MathHelper.ToRadians(180)- signedAngle(s1us, s2us);
s1.speed += Vector2.Transform(s1us, Matrix.CreateRotationZ(angle)) * esc;
s2.speed += Vector2.Transform(s2us, Matrix.CreateRotationZ(angle)) * esc;
}
Any ideas ?
if objects A and B are getting closer, one of the object components (X or Y) is opposite.
in this case Bx is opposite to Ax, so only have to add Ax to the velocity vector of object B, and Bx to velocity vector of object A
If I understood correctly, this is the situation and you want to obtain the two green vectors.
The red vector is easy to get: redVect = pos1 - pos2. redVect and greenVect2 will point to the same direction, so the only step you have is to scale it so its length will match speed2's one: finalGreenVect2 = greenvect2.Normalize() * speed2.Length (although I'm not actually sure about this formula). greenVect1 = -redVect so finalGreenVect1 = greenVect1.Normalize() * speed1.Length. Then speed1 = finalGreenVect1 and speed2 = finalGreenVect2. This approach will give you instant turn, if you prefer a smooth turn you want to rotate the speed vector by:
angle = signedAngle(speed) + (signedAngle(greenVect) - signedAngle(speed)) * 0.5f;
The o.5f is the rotation speed, adjust it to any value you need. I'm afraid that you have to create a rotation matrix then Transform() the speed vector with this matrix.
Hope this helps ;)

Resources