I have UIBezierPathes like this:
And I want to calculate the area size of this kind of custom shapes. I don't have any idea to manage this calculation for this complex shapes in Objective c. I found here something for Android but didn't found something similar for iOS: Click
I dont need a working solution, just need an idea or some pseudo code to solve this problem if there is an way.
Thanks!
If you regions are surrounded by Bezier curves (including straight lines), then you can exploit Green's theorem for parametric curves (formula 10 here) to find area of region. Just calculate value of integral for every curve of contour:
A = Integral[t=0..1] (y(t)*x'(t)*dt)
for cubic Bezier curve, defined by control points P[]:
A = Integral[0..1](y(t)*x'(t)*dt)=
Integral[0..1](
(P[0].Y*(1-t)^3+3*P[1].Y*t*(1-t)^2+3*P[2].Y*t^2*(1-t)+P[3].Y*t^3)*
(P[0].X*(1-t)^3+3*P[1].X*t*(1-t)^2+3*P[2].X*t^2*(1-t)+P[3].X*t^3)' * dt)
We have to expand the brackets, differentiate the second line expression, multiply expressions, and integrate the result. Resulting formulas are rather large, but easy to implement. Maple work to derive formulas:
Related
Suppose you have an image like this:
How can you measure the combined length of all the lines in this image?
I have tried (naively) skeletonising the image and then counting the number of pixels. However, this gives inaccurate results, as diagonal steps are actually longer than vertical/horizontal ones.
My other idea is to generate a chain code for all the line segments , and then use something like Freeman's method to measure the length from the chain code. However, generating the chain code is going to be quite tricky I think, as usually they start/stop at the same point, and this won't work for the grid shape.
Am I missing something obvious here? Is there an easier way to do this?
As far as I can see, the strokes are 3 pixels wide. So dividing the number of black pixels by three isn't a too bad approximation.
Alternatively, use a thinning algorithm to reduce the width to a single pixel (connexity 8), then seed-fill the whole outline. You will use a simple recursive 8-ways fill, and count the lateral and diagonal moves separately. In the end the length is given by L + D√2.
There a is an ellipse on the picture,just as following.
I have got the points of the contour by using opencv. But you can see the pictrue,because the resolution is low, there is a straight line on the contour.How can i fit it into curve like the blue line?
One Of the method to solve your problem is to vectorize your shape (moving from simple intensity space to vectors space).
I am not aware of the state-of-art in this field. However, from school information, I can suggest this solution.
Bezier curves, you can try to model your shape using simple bezier curve.This is not a hard operation you can google for dozen of them. Then, you can resizing it as much as you want after that you may render it to simple image.
Be aware that you may also Splines instead of Bezier.
Another method would be more simple but less efficient. Since you mentioned OpenCV, you can apply the cv::fitEllipse on the points. Be aware that this will return a RotatedRect which contains the ellipse. You can infer your ellipse simply like this:
Center = Center of RotatedRect.
Longest Radius = The Line which pass from the center and intersect with the two small sides of the RotatedRect.
Smallest Radius = The Line which pass from the center and intersect with the two long sides of the RotatedRect.
After you got your Ellipse Parameters, You can resize it as you want then just repaint it in the size you want using cv::ellipse.
I know that this is a pseudo answer. However, I think every thing is easy to apply. If you faced any problem implementing it, just give me a comment.
Given two rectangles, and we know the position of four corners, widths, heights, angles.
How to compute the overlapping ratio of these two rectangles?
Can you please help me out?
A convenient way is by the Sutherland-Hodgman polygon clipping algorithm. It works by clipping one of the polygons with the four supporting lines (half-planes) of the other. In the end you get the intersection polygon (at worst an octagon) and find its area by the polygon area formula.
You'll make clipping easier by counter-rotating the polygons around the origin so that one of them becomes axis parallel. This won't change the area.
Note that this approach generalizes easily to two general convex polygons, taking O(N.M) operations. G.T. Toussaint, using the Rotating Caliper principle, reduced the workload to O(N+M), and B. Chazelle & D. P. Dobkin showed that a nonempty intersection can be detected in O(Log(N+M)) operations. This shows that there is probably a little room for improvement for the S-H clipping approach, even though N=M=4 is a tiny problem.
Use rotatedRectangleIntersection function to get contour and use contourArea function to get area and find the ratios
https://docs.opencv.org/3.0-beta/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html#rotatedrectangleintersection
Lets say you have rectangle A and B the you can use the operation:
intersection_area = (A & B).area();
from this area you can calculate de respective ratio towards one of the rectangles. there will be harder more dynamic ways to do this as well.
Problem is if somebody taps on the angle abc as shown in fig. 1, then the curve should be drawn as shown in fig. 2 using CoreGraphics. I tried it using a Bézier curve, but shapes in different quadrants need dynamic control points which is quite complex (I guess). Can anyone suggest a solution for this?
If I understood it right, then what you need to know is, how to find suitable control points in different quadrant. This link will give you exactly what you want. If you are looking to draw cubic bezier curves then page 18 is for you. However I will recommend you to read it completely to have better understanding of bezier curves.
Formulas given in this paper will help you draw elliptical arcs accurately for one quadrant. You can define your quadrant using angles. To find control points using this paper you need to give following data:
start and end angle (which will define your quadrant)
radii of curve according to your figure
Instead of going through the math , I figured to draw the curve perfect for all the quadrant programmatically.
The algorithm for this is as follows:
(This is an algorithm to find the control points for the Bézier curve perfect for all the quadrants that means you will get the dynamic control points for the Bézier curve.)
Problem: Given 3 points a, b, c, the task is to draw the curve at the angle abc (curve structure is fixed as shown in the figure in the question).
Take all 3 points a, b, c in function.
Transform all 3 points a, b, c to the origin with respect to point a.
Find whether the 3rd point c lies left or right.
Rotate the 2nd point b to coincide the x-axis.
After step 4, you are in the zero position.
(Here you can choose the control points for the Bézier curve like you desire. You do not have to solve any relation for the control points. You can set the control points using simple add/subtract math only.) The control points obtained here will be perfect for all the quadrants.
After step 5, we get all the control points for the Bézier curve, now take all those points to the original position,
a. First rotate point b and the two control points (by the rotation angle of b in step 4)
b. Translate back all points to their original location (i.e. with respect to point a - reversing transformation from step 1).
Now you get the required control points for cubic Bézier suitable for all the quadrants.
Draw the curve using the Bézier curve function.
I've been working on a problem for several weeks and have reached a point that I'd like to make sure I'm not overcomplicating my approach. This is being done in OpenGL ES 2.0 on iOS, but the principles are universal, so I don't mind the answers being purely mathematical in form. Here's the rundown.
I have 2 points in 3D space along with a control point that I am using to produce a bezier curve with the following equation:
B(t) = (1 - t)2P0 + 2(1 - t)tP1 + t2P2
The start/end points are being positioned at dynamic coordinates on a fairly large sphere, so x/y/z varies greatly, making a static solution not so practical. I'm currently rendering the points using GL_LINE_STRIP. The next step is to render the curve using GL_TRIANGLE_STRIP and control the width relative to height.
According to this quick discussion, a good way to solve my problem would be to find points that are parallel to the curve along both sides taking account the direction of it. I'd like to create 3 curves in total, pass in the indices to create a bezier curve of varying width, and then draw it.
There's also talk of interpolation and using a Loop-Blinn technique that seem to solve the specific problems of their respective questions. I believe that the solutions, however, might be too complex for what I'm going after. I'm also not interested bringing textures into the mix. I prefer that the triangles are just drawn using the colors I'll calculate later on in my shaders.
So, before I go into more reading on Trilinear Interpolation, Catmull-Rom splines, the Loop-Blinn paper, or explore sampling further, I'd like to make sure what direction is most likely to be the best bet. I think I can say the problem in its most basic form is to take a point in 3D space and find two parallel points along side it that take into account the direction the next point will be plotted.
Thank you for your time and if I can provide anything further, let me know and I'll do my best to add it.
This answer does not (as far as I see) favor one of the methods you mentioned in your question, but is what I would do in this situation.
I would calculate the normalized normal (or binormal) of the curve. Let's say I take the normalized normal and have it as a function of t (N(t)). With this I would write a helper function to calculate the offset point P:
P(t, o) = B(t) + o * N(t)
Where o means the signed offset of the curve in normal direction.
Given this function one would simply calculate the points to the left and right of the curve by:
Points = [P(t, -w), P(t, w), P(t + s, -w), P(t + s, w)]
Where w is the width of the curve you want to achieve.
Then connect these points via two triangles.
For use in a triangle strip this would mean the indices:
0 1 2 3
Edit
To do some work with the curve one would generally calculate the Frenet frame.
This is a set of 3 vectors (Tangent, Normal, Binormal) that gives the orientation in a curve at a given parameter value (t).
The Frenet frame is given by:
unit tangent = B'(t) / || B'(t) ||
unit binormal = (B'(t) x B''(t)) / || B'(t) x B''(t) ||
unit normal = unit binormal x unit tangent
In this example x denotes the cross product of two vectors and || v || means the length (or norm) of the enclosed vector v.
As you can see you need the first (B'(t)) and the second (B''(t)) derivative of the curve.