Get points on ellipse arc - ios

How to get points to adding identical intervals?
This code works for circle where theta increment by a fixed value
for (theta = 0 -> 360 degrees)
{r = ellipse_equation(theta);
x = r*cos(theta) + h;
y = r*sin(theta) + k;
}
But if increment is fixed for ellipse turns non identical intervals

This doesn't look right to me:
x = r*cos(theta) + h;
y = r*sin(theta) + k;
Shouldn't that actually be
x = cos(theta) * h;
y = sin(theta) * k;
?
And could you please clarify what you mean by "identical intervals"?
Edit:
I don't think there is an 'easy' way to get what you want. Unlike a circle, an ellipse's circumference cannot be trivially calculated: http://en.wikipedia.org/wiki/Ellipse#Circumference, or http://en.wikipedia.org/wiki/Elliptic_integral

Related

Oilfy in OpenCV

I am trying to implement oilfy filter using openCV, and I came across this code.
The code uses gd2 lib. But as my application already uses OpenCV for image processing, its is not recommended to use another lib.
I couldn't understand what the following code does
for (y = 0; y < maskHeight; y++)
{
for (x = 0; x < maskWidth; x++)
{
index = y * maskWidth + x;
rTable[index] = (double) gdImageRed(imageptr,gdImageGetPixel(imageptr,w + x - maskWidth / 2, h + y - maskHeight / 2));
gTable[index] = (double) gdImageGreen(imageptr,gdImageGetPixel(imageptr,w + x - maskWidth / 2, h + y - maskHeight / 2));
bTable[index] = (double) gdImageBlue(imageptr,gdImageGetPixel(imageptr,w + x - maskWidth / 2, h + y - maskHeight / 2));
}
}
Can someone, help me with understanding the oilfy algorithm or tell me how to convert the code into OpenCV?
Any openCV code for oilfy effect will be of much help.
Check out this link -
https://libgd.github.io/manuals/2.2.3/files/gd-c.html#gdImageGetPixel
gdImageGetPixel returns the color value at that pixel in integer format.This contains combination of RGB. The pixel is indicated with gdImagePtr object followed by x and y co-ordinates of the pixel in the image.
gdImageRed returns the red color intensity value in that color, similarly gdImageBlue and gdImageGreen.

Revert a function to get a specific value

I have this function which returns x and y position an just adding up degrees, it make objects to move around in circular movements like a satellite around a planet.
In my case it moves like an ellipse because I added +30 to dist.
-(CGPoint)circularMovement:(float)degrees moonDistance:(CGFloat)dist
{
if(degrees >=360)degrees = 0;
float x = _moon.position.x + (dist+30 + _moon.size.height/2) *cos(degrees);
float y = _moon.position.y + (dist + _moon.size.height/2) *sin(degrees);
CGPoint position= CGPointMake(x, y);
return position;
}
What I would like is to reverse this function, giving the x and y position of an object and getting back the dist value.
Is this possible?
If so, how would I go about achieving it?
If you have an origin and a target, the origin having the coordinates (x1, y1) and the target has the coordinates (x2, y2) the distance between them is found using the Pythagorean theorem.
The distance between the points is the square root of the difference between x2 and x1 plus the difference between y2 and y1.
In most languages this would look something like this:
x = x2 - x1;
y = y2 - y1;
distance = Math.SquareRoot(x * x + y * y);
Where Math is your language's math library.
float x = _moon.position.x + (dist+30 + _moon.size.height/2) *cos(degrees);
float y = _moon.position.y + (dist + _moon.size.height/2) *sin(degrees);
is the way you have originally calculated the values, so the inverse formula would be:
dist = ((y - _moon.position.y) / (sin(degrees))) - _moon.size.height/2
You could calculate it based on x as well, but there is no point, it is simpler based on y.

Image conversion from Cartesian coordinate to polar coordinate

I was wondering if someone helps me understand how to convert the top image to the bottom image.
The images are available in the following link.The top image is in Cartesian coordinate. The bottom image is the converted image in polar coordinate
This is a basic rectangular to polar coordinate transform. To do the conversion, scan across the output image and treat x and y as if they were r and theta. Then use them as r and theta to look up the corresponding pixel in the input image. So something like this:
int x, y;
for (y = 0; y < outputHeight; y++)
{
Pixel* outputPixel = outputRowStart (y); // <- get a pointer to the start of the output row
for (x = 0; x < outputWidth; x++)
{
float r = y;
float theta = 2.0 * M_PI * x / outputWidth;
float newX = r * cos (theta);
float newY = r * sin (theta);
*outputPixel = getInputPixel ( newX, newY ); // <- Should probably do at least bilinear resampling in this function
outputPixel++;
}
}
Note that you may want to handle wrapping depending on what you're trying to achieve. The theta value wraps at 2pi.

How to draw line not line segment OpenCV 2.4.2

Well the question says it all,
I know the function Line(), which draws line segment between two points.
I need to draw line NOT a line segment, also using the two points of the line segment.
[EN: Edit from what was previously posted as an answer for the question]
I used your solution and it performed good results in horizontal lines, but I still got problems in vertical lines.
For example, follows below an example using the points [306,411] and [304,8] (purple) and the draw line (red), on a image with 600x600 pixels. Do you have some tip?
I see this is pretty much old question. I had exactly the same problem and I used this simple code:
double Slope(int x0, int y0, int x1, int y1){
return (double)(y1-y0)/(x1-x0);
}
void fullLine(cv::Mat *img, cv::Point a, cv::Point b, cv::Scalar color){
double slope = Slope(a.x, a.y, b.x, b.y);
Point p(0,0), q(img->cols,img->rows);
p.y = -(a.x - p.x) * slope + a.y;
q.y = -(b.x - q.x) * slope + b.y;
line(*img,p,q,color,1,8,0);
}
First I calculate a slope of the line segment and then I "extend" the line segment into image's borders. I calculate new points of the line which lies in x = 0 and x = image.width. The point itself can be outside the Image, which is a kind of nasty trick, but the solution is very simple.
You will need to write a function to do that for yourself. I suggest you put your line in ax+by+c=0 form and then intersect it with the 4 edges of your image. Remember if you have a line in the form [a b c] finding its intersection with another line is simply the cross product of the two. The edges of your image would be
top_horizontal = [0 1 0];
left_vertical = [1 0 0];
bottom_horizontal = [0 1 -image.rows];
right_vertical = [1 0 -image.cols];
Also, if you know something about the distance between your points you could also just pick points very far along the line in each direction, I don't think the points handed to Line() need to be on the image.
I had the same problem and found out that there it is a known bug on 2.4.X OpenCV, fixed already for newer versions.
For the 2.4.X versions, the solution is to clip the line before plot it using cv::clipLine()
Here there is a function I did to myself that works fine on the 2.4.13 OpenCV
void Detector::drawFullImageLine(cv::Mat& img, const std::pair<cv::Point, cv::Point>& points, cv::Scalar color)
{
//points of line segment
cv::Point p1 = points.first;
cv::Point p2 = points.second;
//points of line segment which extend the segment P1-P2 to
//the image borders.
cv::Point p,q;
//test if line is vertical, otherwise computes line equation
//y = ax + b
if (p2.x == p1.x)
{
p = cv::Point(p1.x, 0);
q = cv::Point(p1.x, img.rows);
}
else
{
double a = (double)(p2.y - p1.y) / (double) (p2.x - p1.x);
double b = p1.y - a*p1.x;
p = cv::Point(0, b);
q = cv::Point(img.rows, a*img.rows + b);
//clipline to the image borders. It prevents a known bug on OpenCV
//versions 2.4.X when drawing
cv::clipLine(cv::Size(img.rows, img.cols), p, q);
}
cv::line(img, p, q, color, 2);
}
This answer is forked from pajus_cz answer but a little improved.
We have two points and we need to get the line equation y = mx + b to be able to draw the straight line.
There are two variables we need to get
1- Slope(m)
2- b which can be retrieved through the line equation using any given point from the two we have already after calculating the slope b = y - mx .
void drawStraightLine(cv::Mat *img, cv::Point2f p1, cv::Point2f p2, cv::Scalar color)
{
Point2f p, q;
// Check if the line is a vertical line because vertical lines don't have slope
if (p1.x != p2.x)
{
p.x = 0;
q.x = img->cols;
// Slope equation (y1 - y2) / (x1 - x2)
float m = (p1.y - p2.y) / (p1.x - p2.x);
// Line equation: y = mx + b
float b = p1.y - (m * p1.x);
p.y = m * p.x + b;
q.y = m * q.x + b;
}
else
{
p.x = q.x = p2.x;
p.y = 0;
q.y = img->rows;
}
cv::line(*img, p, q, color, 1);
}

Draw Perpendicular line to a line in opencv

I better explain my problem with an Image
I have a contour and a line which is passing through that contour.
At the intersection point of contour and line I want to draw a perpendicular line at the intersection point of a line and contour up to a particular distance.
I know the intersection point as well as slope of the line.
For reference I am attaching this Image.
If the blue line in your picture goes from point A to point B, and you want to draw the red line at point B, you can do the following:
Get the direction vector going from A to B. This would be:
v.x = B.x - A.x; v.y = B.y - A.y;
Normalize the vector:
mag = sqrt (v.x*v.x + v.y*v.y); v.x = v.x / mag; v.y = v.y / mag;
Rotate the vector 90 degrees by swapping x and y, and inverting one of them. Note about the rotation direction: In OpenCV and image processing in general x and y axis on the image are not oriented in the Euclidian way, in particular the y axis points down and not up. In Euclidian, inverting the final x (initial y) would rotate counterclockwise (standard for euclidean), and inverting y would rotate clockwise. In OpenCV it's the opposite. So, for example to get clockwise rotation in OpenCV: temp = v.x; v.x = -v.y; v.y = temp;
Create a new line at B pointing in the direction of v:
C.x = B.x + v.x * length; C.y = B.y + v.y * length;
(Note that you can make it extend in both directions by creating a point D in the opposite direction by simply negating length.)
This is my version of the function :
def getPerpCoord(aX, aY, bX, bY, length):
vX = bX-aX
vY = bY-aY
#print(str(vX)+" "+str(vY))
if(vX == 0 or vY == 0):
return 0, 0, 0, 0
mag = math.sqrt(vX*vX + vY*vY)
vX = vX / mag
vY = vY / mag
temp = vX
vX = 0-vY
vY = temp
cX = bX + vX * length
cY = bY + vY * length
dX = bX - vX * length
dY = bY - vY * length
return int(cX), int(cY), int(dX), int(dY)

Resources