How do I skew a pixel-based radial gradient without artifacts? - math

Right now, I am having trouble skewing a radial gradient that is based on sqrt(x^2+y^2). What I would like is a smooth skewing much in the same way that Illustrator have, but for pixel image processing related to distortion.
My attempt to apply a skewed radial gradient for distortion can be seen below:
Description of filter - Use Spiral gradient for finding the x-location of image, and radial gradient for finding y-location.
Then use the values that are found in order to distort the image.
Scripting Language - G'MIC-QT
x is x-location of pixel within for loop
y is y-location of pixel within for loop
w is width
h is height
foo:
r2dx 200%,3#Resize Image using linear interpolation. Used for subpixel processing#
f "begin(
sd=max(w,h)/min(w,h); #Divide the biggest side by the smallest size.#
sx=w>h?sd:1; #Find x-scale to scale x-coordinate#
sy=w>h?1:sd; #Find y-scale to scale y-coordinate#
ang=pi*(0/180); #Convert angle to radian. 0 next to /180 is the function angle.#
slx=2; #Scale of x-coordinate#
sly=2; #Scale of y-coordinate#
skew_x=.15; #Offset x-skewing#
skew_y=.15; #Offset y-skewing#
skew_ang=atan2(skew_y,skew_x)+pi/2; #Find skew angle#
skew_fact=sqrt(skew_x^2+skew_y^2); #Find multiplier for skewing#
srot_x(a,b)=a*cos(skew_ang)-b*sin(skew_ang); #Function for rotating the skewing function#
srot_y(a,b)=a*sin(skew_ang)+b*cos(skew_ang); #Function for rotating the skewing function#
rot_x(a,b)=a*cos(ang)-b*sin(ang); #Distortion Angle Function#
rot_y(a,b)=a*sin(ang)+b*cos(ang); #Distortion Angle Function#
);
XX=(x/w-.5)*2*sx*slx; #Convert x into -1,1 range if image is a square#
YY=(y/h-.5)*2*sy*sly; #Convert y into -1,1 range if image is a square#
SXX=(x/w-.5)*2*sx*slx; #Convert x into -1,1 range if image is a square. Used for skewing!#
SYY=(y/h-.5)*2*sy*sly; #Convert y into -1,1 range if image is a square. Used for skewing!#
xx=rot_x(XX,YY); #Rotation of function#
yy=rot_y(XX,YY); #Rotation of function#
sxx=srot_x(SXX,SYY)*sx*slx; #Rotation of skewing function#
syy=srot_y(SXX,SYY)*sy*sly; #Rotation of skewing function#
skew_atan=atan2(abs(sxx),syy)*skew_fact*sqrt(sxx^2+syy^2);#Generate Skewing Function#
radial=sqrt(xx^2+yy^2)*1+skew_atan; #Combine radial gradient with skewing Function#
if(1,sur_atan=1-(atan2(xx,yy)+pi)/(2*pi);,sur_atan=(atan2(xx,yy)+pi)/(2*pi););#Determine direction of spiral#
es=(sur_atan+radial*1)*1; #Part 1 of Spiral Gradient#
es=es-floor(es); #Part 2 of Spiral#
if(0,es=(es>.5?1-es:es)*2;); #If true, then spiral is continuous, else spiral is non-continuous#
i((es^1)*w,radial*h,z,c,2,3);#i(x-location,y-location,z-location,channel_numbers,interpolation,boundary); The i means image.#
"
r2dx 50%,3 #Resize Image using linear interpolation. Used for subpixel processing#
Target Image
The result using this code
If anything isn't clear, let me know.

I have finally found my solution to the problem. What I did is to make functions to rotate x-coordinate,y-coordinate,boundary box size, and use x-coordinate and y-coordinate to influence the skew factor.
Here's the current G'MIC-QT code for reference. It's hard to explain what I did though.
r2dx 200%,3
f "begin(
sd=max(w,h)/min(w,h);
sx=w>h?sd:1;
sy=w>h?1:sd;
ang=pi*(0/180);
slx=10;
sly=10;
skew_x=.5;
skew_y=.5;
nw=abs(w*sin(ang))+abs(h*cos(ang));
nh=abs(w*cos(ang))+abs(h*sin(ang));
rot_x(a,b)=a*cos(ang)-b*sin(ang);
rot_y(a,b)=a*sin(ang)+b*cos(ang);
);
xx=(x/w-.5)*sx;
yy=(y/h-.5)*sy;
mx=((rot_x(xx,yy)/sx)+.5)*w;
my=((rot_y(xx,yy)/sy)+.5)*h;
nx=mx-abs(skew_x)*rot_x(xx,yy)*(skew_x>0?nw-mx:mx);
ny=my-abs(skew_y)*rot_y(xx,yy)*(skew_y>0?nh-my:my);
xx=(nx/w-.5)*2*slx;
yy=(ny/h-.5)*2*sly;
radial=sqrt(xx^2+yy^2);
if(1,sur_atan=1-(atan2(xx,yy)+pi)/(2*pi);,sur_atan=(atan2(xx,yy)+pi)/(2*pi););
es=(sur_atan+radial*1)*1;
es=es-floor(es);
if(0,es=(es>.5?1-es:es)*2;);
i((es^1)*w,radial*h,z,c,2,3);
"
r2dx 50%,3
Here's the result:

Related

Distance to edge of ellipse given a vector

I've been trying to figure this out for a while and haven't found the answer.
Given:
Height of ellipse,
Width of ellipse,
Xposition of vector,
Ypostion of vector,
Direction of vector.
Find the distance to the edge of the circle
Here's a simple diagram:
Distance to the edge of a circle
I ran across this post: Calculate Point collision between a point of a given vector and the edge of a Circle But this for a circle, not an ellipse.
This is my first time posting on here. I would be very grateful for any help or pointers about this.
One fairly easy way of doing this is to represent both the ellipse and the vector in their cartesian forms
x^2/a^2 + y^2/b^2 = 1 where a & b are the lengths of the semi-major (half the width) and semi-minor (half the height) axes and the centre of the ellipse is assumed to be at (0,0)
and
y - ypos = m(x - xpos) where xpos and ypos are the position of your vector and m is the slope, the cosine of the angle (direction) it makes with the x axis.
Solve them together to get the intercept and use pythagoras to calculate the distance.
This assumes that the centre of the ellipse is at (0,0) and the axes are parallel to the x and y coordinate axes. If this is not the case then you would need a more general equation for the ellipse which is discussed in great detail here in Wikipedia.
As wierdan points out in his comment you can get 0,1 or 2 solutions.
0 if the vector starts outside the ellipse and misses it completely.
1 if the vector is a tangent to the ellipse.
2 if the vector either passes through the ellipse or it's start point is inside the ellipse.
In the case of 2 solutions 0,1 or 2 may be valid
If the vector direction points away from the ellipse then the solutions are for the reciprocal vector, the one pointing 180 degrees in the opposite direction. This may also apply to the tangent solution. So the solution(s) are not valid by your criteria.
If the start point is inside the ellipse then one solution will be for the result you want and the other for the reciprocal vector. So only one solution will be valid.
If the vector passes through the ellipse then both solutions are valid, your choice if you ignore the furthest one.

Calculating the euler angles of a line relative to three axes

I have asked a question similar to this before but have since got further and also didn't tag the question right and wanted to get a bit of help on the maths around the question if possible.
I have a 3D sphere with points evenly spaced on its surface of which I know the coordinates. From these coordinates I am trying to define the orientation of some spikes that are coming out of the surface of my sphere along the vector between the centre of the sphere and the point at which the coordinates lie.
The idea is these euler angles will be very helpful in later aligning the spikes so they are all in roughly the same orientation if I am am to box out all of the spikes from an image.
Since the coordinates on the sphere are evenly spaced i can just take the average x, y and z coordinates to give me the centre and I can then draw a vector from the centre to each coordinate in turn.
The euler angles I need to calculate in this case are initially around the z axis, then around the new y axis, and finally again around the new z axis.
My centre point is currently being defined as the average coordinate of all my coordinates. This works as the coordinates are evenly spaced around the sphere.
I then use the equation that states
cos(theta) = dot product of the two vectors / magnitude of each vector multiplied together
on the x and y axis. One of my vectors is the x and y of the vector i am interested in whilst the other is the y axis (0,1). This tells me the rotation around the z axis with the y axis being 0. I also calculate the gradient of the line on this 2D plane to calculate whether I am working between 0 and +180 or 0 and -180.
I then rotate the x axis about the angle just calculated to give me x' using a simple 2D rotation matrix.
I then calculate the angle in the same way above but this time around the y axis using x' and z' as my second vector (where z' = z).
Finally I repeat the same as stated above to calculate the new z'' and x'' and do my final calculation.
This gives me three angles but when I display in matlab using the quiver3 command I do not get the correct orientations using this method. I believe I just do not understand how to calculate euler angles correctly and am messing something up along the way.
I was hoping someone more knowledgeable than me could take a glance over my planned method of euler angle calculation and spot any flaws.
Thanks.

Rectangle rotation around clipping rectangle center

I have two rectangles where one is a clipping for the other one.
Now I want to rotate the bigger rectangle around the center of the clipping rectangle and adjust x/y values.
How can I calculate the new x/y values after rotation?
I actually just want to rotate the x/y of the bigger box around the center of the smaller box. So the x/y point of the bigger box is relative to the top/left point of the smaller box. I have the width and height of the smaller box so I can calculate x/y point of the big box relative to the center of small box. The angle to rotate is in degrees. The rotation can be any degree, for example 10.
You can do as follows:
determine the angle by which you want to rotate, make sure it suitable for the trigonometric functions (sin(), cos(), ...), i.e. right angle is usually Pi/2
in case of rotating counterclockwise, it is negative
determine the coordinates of c, as cx,cy
process each of the corners of the rectanlge, one by one, for a total of four
for each corner P, currently at coordinates px,py and to move to px2,py2
determine angle between current P and C, using atan2(py-cy, px-cx)
to get from degrees to radians (for use with trigonometry) calculate radians=(pi*degrees)/180.0
add the desired rotation angle to that current angle, to get newangle
determine the distance of current P to C, sqrt((px-cx)(px-cx) + (py-cy)(py-cy))
multiply the distance (which is not changing by rotation), with the appropriate trigonometric function
px2 = distance * cos(newangle)
py2 = distance * sin(newangle)
If you want to rotate a given point P around a point C, which are defined in the same coordinate system you can use a simple rotation matrix. Calculate the P coordinates with respect to C (subtraction), then apply rotation with the matrix and go back to original coordinates by adding C again.
All that matters is the coordinates of the rotation center and the angle.
The most compact formulation is by means of complex numbers (of which I hope you have some understanding; you actually don't need a complex data type, you can expand the formulas).
Let C be the center and α the angle. Then for any point P, the image Q is given by
Q = (P - C) cis(α) + C
where cis(α) = cos(α) + i sin(α).
The inverse rotation is simply given by
P = (Q - C) cis(-α) + C.

Translation coordinates for a circle under a certain angle

I have 2 circles that collide in a certain collision point and under a certain collision angle which I calculate using this formula :
C1(x1,y1) C2(x2,y2)
and the angle between the line uniting their centre and the x axis is
X = arctg (|y2 - y1| / |x2 - x1|)
and what I want is to translate the circle on top under the same angle that collided with the other circle. I mean with the angle X and I don't know what translation coordinates should I give for a proper and a straight translation!
For what I think you mean, here's how to do it cleanly.
Think in vectors.
Suppose the centre of the bottom circle has coordinates (x1,y1), and the centre of the top circle has coordinates (x2,y2). Then define two vectors
support = (x1,y1)
direction = (x2,y2) - (x1,y1)
now, the line between the two centres is fully described by the parametric representation
line = support + k*direction
with k any value in (-inf,+inf). At the initial time, substituting k=1 in the equation above indeed give the coordinates of the top circle. On some later time t, the value of k will have increased, and substituting that new value of k in the equation will give the new coordinates of the centre of the top circle.
How much k increases at value t is equal to the speed of the circle, and I leave that entirely up to you :)
Doing it this way, you never need to mess around with any angles and/or coordinate transformations etc. It even works in 3D (provided you add in z-coordinates everywhere).

Transforming a rectangle into a ring

I have a rectangle that I need to 'bend' into a ring, i.e. the top edge of the rectangle must map to the outer circle of the ring, the bottom to the inner circle, and the sides of the rectangle should join.
Here's an extremely crude sketch of the rectangle and ring:
If it is helpful or necessary, I can deal with the rectangle as a collection of horizontal lines, and the ring as a collection of circles.
The rectangle has a horizontal gradient from a to b that should map so that the gradient progresses on a circular direction.
I can see that this is a non-linear transform, but am lost as to where to look to learn the techniques to solve this problem. Could anyone with suitable experience in CG point me to anything like the right text, the right name of algorithm or the right graphics library to make my ring?
Try just using polar coordinates. If you map x as r and y as θ (normalising as θ runs from 0 to 2π), then adding some offset to r will vary the radius of the ring and adding an offset to θ will rotate it around the circle.
r = fx + a
g = (max_y - min_y)/(2*pi)
theta = gy + b
where a and b are these offsets, f scales the width of the ring and g normalizes the length of the rectangle to 2π. The transform back from these polar coordinates to cartesian (i.e. the screen) is just:
x' = r cos(theta)
y' = r sin(theta)
You then have 3 coordinate systems: (x,y) for the original rectangle, (r,θ) for the polar coordinates of the ring and (x',y') for the screen coordinates.

Resources