Point coordinates at given distance on UIBezierPath - ios

I have a UIBezierPath line and I would like to get the coordinates of a point that is on this line at a given distance of the beginning of this line. By distance I mean distance ALONG the line.
On the following picture, I am looking for x and y.
The perfect solution would be a method that takes the distance as an argument and return the coordinates.
CGPoint myPoint = [myLine pointAtdistance:53.21]
Does something similar exist ? I thought it would be a common problem, but was not able to find any relevant info on the web. Maybe I am searching for the wrong thing ?
Thank you.

If path contains no curve segments, only linear ones, and there is a lot of distance requests for one path, then you can use some preprocessing (1st item):
1. Calculate length of every segment, and cumulative path length till this segment's end
2. With distance request, find proper segment by binary search
(or linear search, if the number of segments is small)
3. Find parameter (0..1) of relative position of point in this segment
4. Calculate coordinates as linear combination of segment end points.
Simple example:
Points (0,0), (1,0), (1,2), (4,-2), (6,-2)
Lengths [1, 2, 5, 2]
Path cumul. lengths: [0, 1, 3, 8, 10]
Distance req.: 5
Binary search finds 3rd segment (5 is between 3 and 8)
3*(1-t)+8*t=5 (equation to find a parameter)
t = 0.4
X = P[2].X * (1-t) + P[3].X * t
Y = P[2].Y * (1-t) + P[3].Y * t
use (1,2) and (4,-2) coordinates
(X,Y)= (2.2, 0.4)

Related

How to find width of a line from its skeleton?

This is similar to a question here But I couldn't use its solution. I'm working in Julia and I'm not sure how it works in this case. Here is an image I'm working on
Due to the curve in line, and unsmooth edges, its not straightforward to get width 'd' of the line. I dont know how to find orthogonal line at each point and get distance d1,d2.. I plan to take its average later to get an estimate of line width. Any tips? Thanks
Using distance transform gets distance from neighbouring pixels, dist = 1 .- distance_transform(feature_transform(Gray.(line_image) .> 0.5)); and lookingup closest pixel with greater distance is the pixel of interest. Using Euclidian distance from an index in centrepoint (skeleton) to nearest distance * 2 gets width of the line.

Anonymising/aggregating lat/long coordinates

I'm looking to display coordinates on a map. The coordinates are at a relatively fine resolution (3 decimal places), but I need to anonymise and aggregate them to a coarser resolution.
All the approaches I've seen run the risk of the coarse coordinates being the same as, or very close to, the original coordinates, since they rely on rounding or adding random noise to the original.
For example, with rounding:
53.401, -2.899 -> 53.4, -2.9 # less than 100m
With adding 'noise', e.g.:
lat = 53.456
// 'fuzz' in range -0.1 to 0.1
rnd = (Math.random() * 2 - 1) * 0.1
newLat = lat + (Math.random() * 2 - 1) * 0.1
However if rnd is close to 0, then the coordinates don't 'move' much.
Is there a (simple) way to 'move' a coordinate in a random way a certain (minimum) distance from it's original location?
I've looked at other answers here but they don't seem to solve this issue of the new coordinates overlapping with the original coordinates:
Rounding Lat and Long to Show Approximate Location in Google Maps
Is there any easy way to make GPS coordinates coarse?
To add random noise, you could displace every point by a fixed distance in a random direction. On a flat projection, for a radius r:
angle = Math.random() * 2 * PI
newLat = lat + (r * sin(angle))
newLon = lon + (r * cos(angle))
That would guarantee a fixed displacement (r) for every point, in an unpredictable direction.
Alternatively, you could anonymise by joining to a polygon at a coarser grain, and then plot the data by the polygon rather than the points. It could be as simple as a grid on a flat projection. Or something more sophisticated such as the Australian Statistical Geography Standard which offers multiple choices, the most granular being a "mesh block" which they guarantee to always contain 30-60 dwellings.
All the approaches I've seen run the risk of the coarse coordinates
being the same as, or very close to, the original coordinates, since
they rely on rounding or adding random noise to the original.
Could you explain, what's the risk that you are concerned about here? Yes, the coarse coordinate might happen to be the same, but it is still anonymized - whoever sees the coarse data would not know if it is coincidentally close or not. All they know is that the actual location is within some distance R_max from the coarse location.
Re the other solution,
displace every point by a fixed distance in a random direction
I would say it is much worse: here it would be easy to discover the fixed displacement distance by knowing just a single original location. Then, for any "coarse" location, we would know the original is on thin unfilled circle centered on the "coarse" location - much worse than the filled circle or rectangle in the original solution.
At the very least, I would use random radius, maybe don't allow it to be zero, if you are concerned about coincidental collision (but you should not be). E.g. this varies the radius from r_max / 2 to r_max:
r = (Math.random() + 1) * r_max / 2;
and then you can use this random radius with Schepo's solution.

Hough Transform Accumulator to Cartesian

I'm studying a course on vision systems and one of the questions posed was;
For the accumulator shown;
Determine the most likely r,θ combination representing the straight line of the greatest strength in the original image.
From my understanding of the accumulator this would be r = 60, θ = 150 as the 41 votes is the highest number of votes in this cluster of large votes. Am I correct with this combination?
And hence calculate the equation of this line in the form y = mx + c
I'm not sure of the conversion steps required to convert the r = 60, θ = 150 to y = mx + c with the information given since r = 60, θ = 150 denotes 1 point on the line.
State the resolution of your answer and give your reasoning
I assume the resolution is got to do with some of the steps in the auscultation and not the actual resolution of the original image since that's irrelevant to the edges detected in the image.
Any guidance on the above 3 points would be greatly appreciated!
Yes, this is correct.
This is asking you what the slope and intercept are of the line given r and theta. r and theta are not one point on the line, they are one point of the accumulator. r and theta describe a line using the line equation in polar coordinates: . This is the cool thing about the hough transform, every line in one space, (i.e. image space) can be described by a point in another space (r, theta). This could be done with m and b from the line equation , but as we all know, m is undefined for vertical lines. This is the reason the polar line equation is used. It is important to note that the line described by the HT r and theta refers to a line from the origin extending to the actual line in the image. This means your image line y = mx + b equation will need to be orthogonal to the polar equation. The wiki article on the HT describes this well and shows examples. I would recommend drawing a diagram of your r and theta extending to a line like this:
Then use trig to get two points on the red line. Two points are enough to give you m and b from the line equation.
I'm not entirely sure what "resolution" refers to in this context. But it does seem like your line estimator will have some precision loss since r is every 20 mm and theta is every 15 degrees. Perhaps it is asking what degree of error you could get given an accumulator of this resolution.

OpenCV calculate distance from object with known size

Is it possible to calculate the distance of an object with known size?
I would like to do this with an ball which has 7cm diamater. Now for the first calculation I would put him in 30cm distance to the webcam and in the second 50cm.
Is there a linear function or formular to calculate somehow the distance?
Lets say in the first measure it has a diamater of 6 pixel and in the second only 4. There must be a formular for this?
Best regards
In optical scheme you have two similar right triangles with edges F (objective focus distance), PixelSize, Distance and Size
Distance / Size = F / PixelSize
So having parameters for some known Distance0, you can get F (in pixel units, consider it as some constant)
F = Distance0 * PixelSize0 / Size0
and use it to calculate unknown distance (until zoom changes)
Distance = F * Size / PixelSize
(Note that you can vary object size)

Moving multiple sprites in elliptical path with uniform speed

I'm trying to move multiple sprites (images) in an elliptical path such that distance (arc distance) remains uniform.
I have tried
Move each sprite angle by angle, however the problem with this is that distance moved while moving unit angle around major axis is different than that while moving unit angle around minor axis - hence different distance moved.
Move sprites with just changing x-axis uniformly, however it again moves more around major axis.
So any ideas how to move sprites uniformly without them catching-up/overlapping each other?
Other info:
it will be called in onMouseMove/onTouchMoved so i guess it shouldn't
be much CPU intensive.
Although its a general algorithm question but
if it helps I'm using cocos2d-x
So this is what i ended up doing (which solved it for me):
I moved it in equation of circle and increased angle by 1 degree. Calculated x and y using sin/cos(angle) * radius. And to make it into an ellipse I multiplied it by a factor.
Factor was yIntercept/xIntercept.
so it looked like this in end
FACTOR = Y_INTERCEPT / X_INTERCEPT;
//calculate previous angle
angle = atan((prev_y/FACTOR)/prev_x);
//increase angle by 1 degree (make sure its not radians in your case)
angle++;
//new x and y
x = cos(newangle) * X_INTERCEPT;
y = sin(newangle) * X_INTERCEPT * FACTOR;
I have written a function named getPointOnEllipse that allows you to move your sprites pixel-by-pixel in an elliptical path. The function determines the coordinates of a particular point in the elliptical path, given the coordinates of the center of the ellipse, the lengths of the semi-major axis and the semi-minor axis, and finally the offset of the point into the elliptical path, all in pixels.
Note: To be honest, unfortunately, the getPointOnEllipse function skips (does not detect) a few of the points in the elliptical path. As a result, the arc distance is not exactly uniform. Sometimes it is one pixel, and sometimes two pixels, but not three or more! In spite of the fault, changes in speed will be really "faint", and IMO, your sprites will move pretty smoothly.
Below is the getPointOnEllipse function, along with another function named getEllipsePerimeter, which is used to determine an ellipse's perimeter through Euler's formula. The code is written in JScript.
function getEllipsePerimeter(rx, ry)
{
with (Math)
{
// You'll need to floor the return value to obtain the ellipse perimeter in pixels.
return PI * sqrt(2 * (rx * rx + ry * ry));
}
}
function getPointOnEllipse(cx, cy, rx, ry, d)
{
with (Math)
{
// Note: theta expresses an angle in radians!
var theta = d * sqrt(2 / (rx * rx + ry * ry));
//var theta = 2 * PI * d / getEllipsePerimeter(rx, ry);
return {x:floor(cx + cos(theta) * rx),
y:floor(cy - sin(theta) * ry)};
}
}
The following figure illustrates the parameters of this function:
cx - the x-coordinate of the center of the ellipse
cy - the y-coordinate of the center of the ellipse
rx - the length of semi-major axis
ry - the length of semi-minor axis
d - the offset of the point into the elliptical path (i.e. the arc length from the vertex to the point)
The unit of all parameters is pixel.
The function returns an object containing the x- and y-coordinate of the point of interest, which is represented by a purple ball in the figure.
d is the most important parameter of the getPointOnEllipse function. You should call this function multiple times. In the first call, set d to 0, and then place the sprite at the point returned, which causes the sprite to be positioned on the vertex. Then wait a short period (e.g. 50 milliseconds), and call the function again, setting d parameter to 1. This time, by placing the sprite at the point returned, it moves 1 pixel forward in the ellipse path. Then repeat doing so (wait a short period, call the function with increased d value, and position the sprite) until the value of d reaches the perimeter of the ellipse. You can also increase d value by more than one, so that the sprite moves more pixels forward in each step, resulting in faster movement.
Moreover, you can modify the getEllipsePerimeter function in the code to use a more precise formula (like Ramanujan's formula) for getting ellipse perimeter. But in that case, be sure to modify the getPointOnEllipse function as well to use the second version of theta variable (which is commented in the code). Note that the first version of theta is just a simplified form of the second version for the sake of optimization.

Resources