How to determine the first triangle (out of a set of triangles) passed through by a 3-D ray? - python

I am trying to solve the following problem in Python. The problem comes from an image processing problem when i use the Finite Element Method.
In my problem, I have a set of triangles and a ray. Each triangle consists of three 3-D points, and the ray is in the form of a 3-D point and a 3-D vector. How can I determine the first triangle that is passed through by the ray? Now I do not even have an algorithm for this. Any inputs will be appreciated.

The first thing I would do, is translate the whole data set, subtracting the 3D ray origin. Then rotate the data set so that the ray's 3D vector aligns with the X-axis. See How to find the orthonormal transformation that will rotate a vector to the x axis?.
Now the problem has been converted to filter for triangles that cross the X-axis with a non-negative X-coordinate, and among those find the one whose crossing point has the minimal X-coordinate. So
For each triangle check where its plane crosses the X-axis. See Determine point of interesction of plane with axis given points of plane
Then throw away the triangles where that crossing point (on the X-axis) is not within the bounds of the triangle (check for each of the three edges that this point is at the "inner" side of it). See Check whether a point is within a 3D Triangle
Throw away the triangles whose crossing point has a negative X-coordinate.
Among the remaining triangles (that really cross the X-axis on the positive side) find the one with the minimum crossing point in terms of X-coordinate.

Related

Cutting a matrix for a certain complex shape - Python

I ran into a problem that I don't know how to address, if anyone has any ideas I would be very grateful.
So I have a NxM matrix and number of points (minimum 4) that represent a shape resting on the matrix as show in the figure (Each point is represented by a number, ignore the black/white points):
I know how to match each point to the x,y coordinate inside the matrix.
But let's say I want to calculate the average of the values inside the polygon, how can I do it?
Many thanks to all the helpers
I tried to parametrize the polygon to a new square, but without success...
You need to use a polygon filling algorithm (also called scan conversion). In a nutshell, you intersect the polygon with all horizontals through the matrix rows and find intervals covered by the inside of the polygon. Accumulate the matrix values spanned by these intervals.

Determining Best Fit Center of Scattered 3D Points

I am attempting to find the center of several sets of 3D points on a sphere. Each set is comprised of three or more points that fall on the arc of a circle, but not perfectly as they have been supplied by an object detection algorithm, so there is some inherent error in these points. This is for me where the difficulty lies, I cannot simply solve the equations, I need to try and minimize variance in radius to this point across all three-point sets.
Currently, I am calculating a plane of best fit for each set of points. By calculating the radius (perpendicular distance) to this normal for each set and determining the variance I can figure out which plane (normal or center of rotation) fits all three sets the best. I am also doing this for an average of the three planes and for two planes after throwing out the plane that agrees least with the other two. So I am getting a pretty decent approximation currently.
My question is, does anyone know how to implement in Python some sort of function that can help me find a normal vector through these points that minimize the variance in radius for all sets. I suspect this won't be far off my current approximation, but am looking for the most accurate solution to this problem.
The picture below shows the results of what I am currently doing. The pink points represent the points I am using, labeled 0,1,2 for each set of points. The blue dots represent the normal vector projected to the surface of the sphere. The orange is the average of the three blue dots projected to the surface of the sphere. Ignore green they are not relevant to this. To minimize the variance my code is currently telling me that axis (blue dot) 0 results in the least variance in radius for the data set as a whole, but I highly doubt it is the best fitting point.

Python library for rotation and translation on a seesaw-like object

I'd like to do calculations on the 3D positions on both end's of a rigid object (see spot where the children are usually sitting in image below). The geometrical situation of the rigid object corresponds to a seesaw. Rotation has to be possible on three axes and can be represented by a ball bearing, which initially is located at the middle of the rod.
The input to the desired function should consist of three rotations performed at the position of the ball bearing, three translations along the bearing and the initial 3D positions of both ends of the object.
The output needs to be the calculated new 3D positions of both ends.
Does anyone know a python library that does provide functionalities regarding this issue?
I've just found out that Open3D has implemented exactly what I was looking for. As it is working with point clouds, all that needs to be done is to create two points in 3D space, define a rotation matrix and the center (= ball bearing in this case). The function "rotate" then calculates the altered positions of the rotated points. This also works for translation.
# Rotation
pcd.rotate(r, center = (0,0,0))
# Translation
pcd.translate(t)
With r = rotation matrix (3x3) and t = translation matrix (3x1).

Curvature of a one-pixel wide curve

I have a numpy array depicting a one-pixel wide, discrete, connected curve. This curve is obtained by the Skeletonization operation of image processing. I am trying to find the curvature of the above curve at an arbitrary point, to detect bends/kinks (which will have high curvature value).
I tried to implement the above using the general formula for curvature. However, since this a pixelated, discrete curve, whose generating function is unknown, I tried to resort to using numpy gradient instead.
The problem I see with the above is that, since the curve is one-pixel wide, at any point the slope can be only one of 0, 1 or infinity. As a result, the curvature values that I get are mostly meaningless or useless.
I am looking for some suggestion on where to start in order to get a smooth curve out of the above, so that I can calculate curvature in a more meaningful way. Can somebody suggest any mathematical operation or convolution that I can apply to achieve the same? Below is a representative binary image that I have.
P.S. I am very, very new to image processing, so references to standard algorithms (in math books) or library implementations would be very helpful.
An established way to do this is to fit a low-order parametric curve to each of the skeletonized points using two or more neighbouring points. Then you compute curvature at the point using the fitted curve parameters with an analytic formula. Several curve models can be used. The two main models are:
A circle. The radius of curvature, R is the reciprocal of the curvature. For a curve, it equals the radius of the circular arc which best approximates the curve at that point. You can fit a circle to a set of 2D data points using various methods. A python library that has implemented several is here.
A quadratic. This can be fitted to the point and its neighbours, then curvature can be estimated through second-order differentiation of the curve here. You can use numpy.polyfit to fit this model. A simple strategy is to first estimate the tangent vector at the point, by fitting a local line (e.g. with polyfit using an order 1 curve). The you rotate the points to align the tangent vector with the x axis. Finally you fit a 1D quadratic f(x) to the rotated points using polyfit.
The tricky thing with making any curvature estimator is that curvature can be estimated at different scales. For example, do I want my estimator to be sensitive to high frequency detail or is this actually noise? This decision manifests in the choice of neighbourhood size. Too small, and errors from noise and discretization lead to unstable estimates. However too large, and there may be large modelling error (error by approximating the curve as a parametric function). Generally you have to select the best neighbourhood size yourself.
You're also going to have some poor curvature estimates at junction points, but that's largely unavoidable as curvature is not well defined there. A naïve fix could be to segment all paths at junction points, and then estimate curvature on each path individually.
Toby gave an excellent suggestion regarding junction points: detect the junction points and take each line in between those independently.
Detecting junction points (and end points). This is quite simple: all pixels that are set and have more than two neighbors are junction points. All pixels that are set and have exactly one neighbor are end points. Detect all those points and put their coordinates in a list.
Finding the lines in between pairs of points. Starting at each coordinate in your list, look for a line starting there. Note that for the junction points, you'll have at least three lines starting there. If you do this, you'll find each line two times. You can remove duplicates by reversing the lines that end to the left of where they start (and if the two end points are on the same image column, take the one on top as the start). Now they will be directly comparable, so you can delete the duplicates (or not store them in the first place). Note that just comparing start and end point is not sufficient as you can have different lines with the same start and end points.
Tracing each line. The step above requires that you trace each line. See if you can figure it out, it's fun! Here is a description of an algorithm that traces the outline of objects, you can use it as inspiration as this problem is very similar. Store a vector with x-coordinates and one with y-coordinates for each line.
Smoothing the lines. As you noticed, consecutive steps are in one of 8 directions, so angles are strongly discretized. You can prevent this by smoothing the coordinate vectors. This is a quick-and-dirty trick, but it works. Think of these vectors as 1D images, and apply a smoothing filter (I prefer the Gaussian filter for many reasons). Here you filter the vector with x-coordinates separately from the vector with y-coordinates.
Computing the curvature. Finally, you can compute the curvature of the curve, as the norm of the derivative of the unit normal to the curve. Don't forget to take the distance between points into account when computing derivatives!

Unordered cloud point of polygon contour to polygon

Dear Stackoverflow community,
I have contours of irregular polygons as unordered datapoints (like on the figure here: https://s16.postimg.org/pum4m0pn9/figure_4.png), and I am trying to order them (ie. to create a polygon).
I cannot use the convex hull envelope because of the non convex shape of the polygon. I cannot ase a minimum distance criterion because some points of other parts of the contour lie closer (example: point A has to be joined with B, but is closer to C). I cannot use a clockwise ordering because of the irregular shape of the contour.
Do anyone knos a way to implement (preferentially in Python) an algorithm that would reorder the datapoints from a starting point?
look here finding holes in 2D point set for some ideas on how to solve this
I would create point density map (similar to above linked answer)
create list of all lines
so add to it all possible combination of lines (between close points)
not intersecting empty area in map
remove all intersecting lines
apply closed loop / connectivity analysis on the lines
then handle the rest of unused points
by splitting nearest line by them ...
depending on you map grid size and point density you may need to blend/smooth the map to cover gaps
if grid size is too big then you can miss details like on the image between points A,C
if it is too small then significant gaps may occur near low density areas
But as said this has more then one solution so you need to tweak this a bit to make the wanted output perhaps some User input for shaking the solution a bit until wanted solution found...
[notes]
you can handle this as more covex polygons ...
add line only if winding rule met
stop when no more lines found
start again with unused points
and in the end try to connect found non closed polygons ...

Categories