Determine if a polygon is star-shaped - algorithm

I need some hints on this one:
A polygon P is star-shaped if there exists a point p in the interior of P such that any other point (vertex) on the boundary is visible to p.
Given a polygon P, how can i determine if P is a star shaped polygon?
Time complexity should be o(n) on average.
Ive been sitting on this for a while now, Any help will be appericiated.

very weird definition of star according to that circle and pie are also stars ...
First simple and O(n) possibility I can think of is to render visibility map:
compute BBOX of the shape
create 2D map of the BBOX and clear it with zero
so map 2D array (texture) to the BBOX of some resolution xs*ys
for each convex vertex increment visibility map
simply by rendering "infinite" triangle/quad onto the map
You can use winding rule to chose if vertex is convex or concave by simply checking the sign of z coordinate of the adjacent edges cross product against the winding rule of your shape.
scan the 2D map for cells containing number of convex vertexes
all the cells/pixels containing number of convex vertexes are your possible Z so if any found your shape is a "star".
This is O(n*xs*ys) where n is number of (convex) vertexes and xs*ys is resolution of the visibility map. Note if your resolution is too low due to inaccuracies you might produce false negatives/positives ... if (max) resolution of the map is constant then the complexity will turn to O(n).
The rendering can be done simply for example with OpenGL and STENCIL buffer which directly has operation to increment STENCIL pixel however that one will limit the n to 255 as STENCIL is only 8 bit these days (after changes in OpenGL)... However you can workaround this by seting the BBOX to 1 and clear the exterior of the triangle/quad instead of incrementing its interrior. then the pixels holding 1 are your Z this might be used with any rendering engine no need for STENCIL

Related

3D mesh direction detection

I have a 3D mesh consisting of triangle polygons. My mesh can be either oriented left or right:
I'm looking for a method to detect mesh direction: right vs left.
So far I tried to use mesh centroid:
Compare centroid to bounding-box (b-box) center
See if centroid is located left of b-box center
See if centroid is located right of b-box center
But the problem is that the centroid and b-box center don't have a reliable difference in most cases.
I wonder what is a quick algorithm to detect my mesh direction.
Update
An idea proposed by #collapsar is ordering Convex Hull points in clockwise order and investigating the longest edge:
UPDATE
Another approach as suggested by #YvesDaoust is to investigate two specific regions of the mesh:
Count the vertices in two predefined regions of the bounding box. This is a fairly simple O(N) procedure.
Unless your dataset is sorted in some way, you can't be faster than O(N). But if the point density allows it, you can subsample by taking, say, every tenth point while applying the procedure.
You can as well keep your idea of the centroid, but applying it also in a subpart.
The efficiency of an algorithm to solve your problem will depend on the data structures that represent your mesh. You might need to be more specific about them in order to obtain a sufficiently performant procedure.
The algorithms are presented in an informal way. For a more rigorous analysis, math.stackexchange might be a more suitable place to ask (or another contributor is more adept to answer ...).
The algorithms are heuristic by nature. Proposals 1 and 3 will work fine for meshes whose local boundary's curvature is mostly convex locally (skipping a rigorous mathematical definition here). Proposal 2 should be less dependent on the mesh shape (and can be easily tuned to cater for ill-behaved shapes).
Proposal 1 (Convex Hull, 2D)
Let M be the set of mesh points, projected onto a 'suitable' plane as suggested by the graphics you supplied.
Compute the convex hull CH(M) of M.
Order the n points of CH(M) in clockwise order relative to any point inside CH(M) to obtain a point sequence seq(P) = (p_0, ..., p_(n-1)), with p_0 being an arbitrary element of CH(M). Note that this is usually a by-product of the convex hull computation.
Find the longest edge of the convex polygon implied by CH(M).
Specifically, find k, such that the distance d(p_k, p_((k+1) mod n)) is maximal among all d(p_i, p_((i+1) mod n)); 0 <= i < n;
Consider the vector (p_k, p_((k+1) mod n)).
If the y coordinate of its head is greater than that of its tail (ie. its projection onto the line ((0,0), (0,1)) is oriented upwards) then your mesh opens to the left, otherwise to the right.
Step 3 exploits the condition that the mesh boundary be mostly locally convex. Thus the convex hull polygon sides are basically short, with the exception of the side that spans the opening of the mesh.
Proposal 2 (bisector sampling, 2D)
Order the mesh points by their x coordinates int a sequence seq(M).
split seq(M) into 2 halves, let seq_left(M), seq_right(M) denote the partition elements.
Repeat the following steps for both point sets.
3.1. Select randomly 2 points p_0, p_1 from the point set.
3.2. Find the bisector p_01 of the line segment (p_0, p_1).
3.3. Test whether p_01 lies within the mesh.
3.4. Keep a count on failed tests.
Statistically, the mesh point subset that 'contains' the opening will produce more failures for the same given number of tests run on each partition. Alternative test criteria will work as well, eg. recording the average distance d(p_0, p_1) or the average length of (p_0, p_1) portions outside the mesh (both higher on the mesh point subset with the opening). Cut off repetition of step 3 if the difference of test results between both halves is 'sufficiently pronounced'. For ill-behaved shapes, increase the number of repetitions.
Proposal 3 (Convex Hull, 3D)
For the sake of completeness only, as your problem description suggests that the analysis effectively takes place in 2D.
Similar to Proposal 1, the computations can be performed in 3D. The convex hull of the mesh points then implies a convex polyhedron whose faces should be ordered by area. Select the face with the maximum area and compute its outward-pointing normal which indicates the direction of the opening from the perspective of the b-box center.
The computation gets more complicated if there is much variation in the side lengths of minimal bounding box of the mesh points, ie. if there is a plane in which most of the variation of mesh point coordinates occurs. In the graphics you've supplied that would be the plane in which the mesh points are rendered assuming that their coordinates do not vary much along the axis perpendicular to the plane.
The solution is to identify such a plane and project the mesh points onto it, then resort to proposal 1.

Snapping vector to a point from a grid on a sphere (icosahedron)

here is a problem that will turn your brain inside out, I'm trying to deal with it for a quite some time already.
Suppose you have sphere located in the origin of a 3d space. The sphere is segmented into a grid of equidistant points. The procedure that forms grid isn't that important but what seems simple to me is to use regular 3d computer graphics sphere generation procedure (The algorithm that forms the sphere described in the picture below)
Now, after I have such sphere (i.e. icosahedron of some degree) I need a computationally trivial procedure that will be capable to snap (an angle) of a random unit vector to it's closest icosahedron edge points. Also it is acceptable if the vector will be snapped to a center point of triangle that the vector is intersecting.
I would like to emphasise that it is important that the procedure should be computationally trivial. This means that procedures that actually create a sphere in memory and then involve a search among every triangle in sphere is not a good idea because such search will require access to global heap and ram which is slow because I need to perform this procedure millions of times on a low end mobile hardware.
The procedure should yield it's result through a set of mathematical equations based only on two values, the vector and degree of icosahedron (i.e. sphere)
Any thoughts? Thank you in advance!
============
Edit
One afterthought that just came to my mind, it seems that within diagram below step 3 (i.e. Project each new vertex to the unit sphere) is not important at all, because after bisection, projection of every vertex to a sphere would preserve all angular characteristics of a bisected shape that we are trying to snap to. So the task simplifies to identifying a bisected sub triangle coordinates that are penetrated by vector.
Make a table with 20 entries of top-level icosahedron faces coordinates - for example, build them from wiki coordinate set)
The vertices of an icosahedron centered at the origin with an
edge-length of 2 and a circumscribed sphere radius of 2 sin (2π/5) are
described by circular permutations of:
V[] = (0, ±1, ±ϕ)
where ϕ = (1 + √5)/2
is the golden ratio (also written τ).
and calculate corresponding central vectors C[] (sum of three vectors for vertices of every face).
Find the closest central vector using maximum of dot product (DP) of your vector P and all C[]. Perhaps, it is possible to reduce number of checks accounting for P components (for example if dot product of P and some V[i] is negative, there is no sense to consider faces being neighbors of V[i]). Don't sure that this elimination takes less time than direct full comparison of DP's with centers.
When big triangle face is determined, project P onto the plane of that face and get coordinates of P' in u-v (decompose AP' by AB and AC, where A,B,C are face vertices).
Multiply u,v by 2^N (degree of subdivision).
u' = u * 2^N
v' = v * 2^N
iu = Floor(u')
iv = Floor(v')
fu = Frac(u')
fv = Frac(v')
Integer part of u' is "row" of small triangle, integer part of v' is "column". Fractional parts are trilinear coordinates inside small triangle face, so we can choose the smallest value of fu, fv, 1-fu-fv to get the closest vertice. Calculate this closest vertex and normalize vector if needed.
It's not equidistant, you can see if you study this version:
It's a problem of geodesic dome frequency and some people have spent time researching all known methods to do that geometry: http://geo-dome.co.uk/article.asp?uname=domefreq, see that guy is a self labelled geodesizer :)
One page told me that the progression goes like this: 2 + 10·4N (12,42,162...)
You can simplify it down to a simple flat fractal triangle, where every triangle devides into 4 smaller triangles, and every time the subdivision is rotated 12 times around a sphere.
Logically, it is only one triangle rotated 12 times, and if you solve the code on that side, then you have the lowest computation version of the geodesic spheres.
If you don't want to keep the 12 sides as a series of arrays, and you want a lower memory version, then you can read about midpoint subdivision code, there's a lot of versions of midpoint subdivision.
I may have completely missed something. just that there isn't a true equidistant geodesic dome, because a triangle doesn't map to a sphere, only for icos.

How to Judge the Equality of 2 Triangular Meshes?

Given a triangular mesh A in 3D space. Rotate and translate all its points to generate a new mesh B.
How to determine the equality of A and B, just by their vertices and faces?
Topology of the mesh is not important, I only care about the geometric equality, A and B should be equal even if their triangulation are changed. It is
something like the transform in-variance problem for triangular mesh, only translate and rotation is considered.
To complete #Spektre's answer, if the two meshes are not exactly the same, that is there is at least a pair of nodes or edges which does not perfectly overlap, You can use the Hausdorff distance to quantify the "difference" between the two meshes.
Assuming triangle faces only.
compare number of triangles
if not matching return false.
sort triangles by their size
if the sizes and order does not match between both meshes return false.
find distinct triangle in shapes
So either the biggest or smallest in area, edge length or whatever. If not present then you need other distinct feature like 2 most distant points etc ... If none present even that then you need the RANSAC for this.
Align both meshes so the matching triangles (or feature points) will have the same position in both meshes.
compare matching vertexes
so find the closest vertex form Mesh A to each vertex in mesh B and if the distance of any them cross some threshold return false
return true
In case meshes has no distinct features for 3 you need to either use brute force loop through all combinations of triangles form A and B until #4 returns true or all combinations tested or use RANSAC for this.
There are alternatives to #3 like find the centroid and closest and farthermost points to it and use them as basis vectors instead of triangle. that requires single vertex or close group of vertexes to be the min and max. if not present like in symmetrical meshes like cube icosahedron, sphere you're out of luck.
You can enhance this by using other features from the mesh if present like color, texture coordinate ...
[Edit1] just a crazy thinking on partial approach without the need of aligninig
compute average point C
compute biggest inscribed sphere centered at C
just distance from C to its closest point
compute smallest outscribed sphere centered at C
just distance from C to its farthest point
compare the radiuses between the shapes
if not equal shapes are not identical for sure. If equal then you have to check with approaches above.
The paper On 3D Shape Similarity (Heung-yeung Shum, Martial Hebert, Katsushi Ikeuchi) computes a similarity score between two triangular meshes by comparing semiregular sphere tessellations that have been deformed to approximate the original meshes.
In this case, the meshes are expected to be identical (up to some small error due to the transformation), so an algorithm inspired by the paper could be constructed as follows:
Group the vertices of each mesh A, B by the number of neighboring vertices they have.
Choose one vertex V_A from mesh A and vertex V_Bi from mesh B, both with same number of neighbors.
The vertex and its N neighbors V_n1...V_nN form a triangle fan of N triangles. Construct N transforms which take vertex V_Bi to V_A and each possible fan (starting from a different neighbor V_Bn1, V_Bn2, ..., V_BnN) to V_An1...V_AnN.
Find the minimum of the sums of distances from each vertex of B to the closest vertex to it in A, for each N transforms for each vertex V_Bi.
If a sum of near zero is found, the vertices of the transformed mesh B coincide with vertices of A, a mapping between them can be constructed, and you can do further topological, edge presence or direction checks, as needed.

How to convert a regular height grid to a triangular irregular network?

I'm looking for an algorithm that converts a regular grid of heights (e.g. 1024x1024) to a triangular irregular network. Here is an image showing an example of a triangular irregular network:
I've looked in the internet for an algorithms to convert it, but I just couldn't find one. Basically the triangle density depends on the roughness and/or pixel error (when rasterized), or something like that.
Here's an idea for a two-step algorithm: Do a Delaunay triangulation based on a rough mesh first, then smoothe out the triangles recursively until a certain error criterion is met.
For the first step, identify a set of vertices for the Delaunay triangulation. These vertices coincide with pixel coordinates. Extreme points that are either higher or lower than all four neighbouring pixels should be in the set as should ridge points on the borders where the adjacent pixels along the border are either lower or higher. This should give a coarse triangular mesh. You can get a finer mesh by also including pixels that have a high curvature.
In the second step, iterate through all triangles. Scan through the triangle along the pixel grid and accumulate an error square for each pixel inside the triangle and also identify the points of maximum and minimum signed error. If the average error per pixel does not meet your criterion, add the points of lowest and highest error to your triangulation. Verify the new triangles and re-triangulate as necessary.
Notes:
The coarse triangulation in step one should be reasonably fast. If the height map is ragged, you might end up with too many vertices in the ragged area. In that case, the hight map might be smoothed with a Gaussian filter before applying the algorithm.
The recursive re-triangulation is probably not so fast, because determining the error requires scanning the triangles over and over. (The process should get faster as the triangle size decreases, but still.) A good criterion for finding vertices in step 1 might speed up step 2.
You can scan a triangle by finding the bounding box of pixels. Find the barycentric coordinates s, t of the lower left point of the bounding box and also the barycentric increments (dsx, dtx) and (dsy, dty) that correspond to a pixel move in the x and y directions. You can then scan the bounding box in two loops over the included pixels (x, y), calculate the barycentric coordinates (s, t) from your delta vectors and accumulate the error if you are inside the triangle, i.e. when s > 0, t > 0 and s + t < 1.
I haven't implemented this algorithm (yet - it is an interesting task), but I imagine that finding a good balance between speed and mesh quality is a matter of tailoring error criteria and vertex selection to the current height map.

collision prediction using minkowski sum

I want to use the minkowski sum to predict the exact point of collision between two convex shapes. By my understanding the point where the velocity vector intersects with the minkowski sum is the amount I have to move my object along the vector so they just touch (I already know they will collide). Here's an example of what I mean (for simplicity reasons I just used rectangles):
I mean I could just calculate the intersection with every line of the convex hull and just use the closest but that seems horribly inefficient. My idea was to calculate the simplex closest to the vector but I have no idea how best to do it. I found a algorithm which calculates the smallest distance between to objects or to be more precise the smallest distance from the minkowski sum to the origin (http://www.codezealot.org/archives/153). One part of the algorithm tries to find the simplex closest to origin which is kinda what I want to do. I tried to change it to my needs but I wasn't successful. To me it sounds like there should be a very simple solution but I am not that good with vector math.
I hope I could make my problem clear since my english is not so good :D
You can transform the problem as follows:
1) rotate the plane so that the velocity vector becomes horizontal
2) consider the portions of the polygon outlines facing each other (these are two convex polylines); now you have to find the shortest horizontal distance between these two polylines
3) through every vertex of one of the polylines, draw an horizontal line; this will parition the plane into a set of horizontal slices
4) transform every slice using a shear transformation that brings the two vertices defining it onto the Y axis by horizontal moves; this transform preserves horizontal distances
5) while the first polyline is transformed into a straight line (the Y axis), the other polyline is transformed into another polyline; find the vertex(es) closest to the Y axis. This gives you the length of the collision vector.
As a by-product, step 2) will tell you if the polygons do collide, if the ranges of Y values overlap.

Resources