Generate topological information from STL file - data-structures

What would be the best way to generate topological information for an object loaded from a STL file (STL stores just 3 vertices for each face). As a result I would like a winged-edge data structure or something similar.

Main issue is to find all unique point positions, so that triangles can be represent as list of point ids (indices) instead as list of coordinates. To do that some nearest neighbour data structure is used. In this case, I think best are space partition data structures.
With that you can get list of unique point positions, and list of triangles that are represented as triple of indices in the list of points. To create winged edge data structure or similar 'connectivity' structure, you have to find all different edges (pairs of points that are in some triangle) and store connectivity data that you need (in which triangles is edge used, for a point in which edges and/or triangles is used, ...)

Related

How to use A* with the following map

I'm developing a robot simulation using ROS and C++.
I have created a map, which is a list of free positions in a closed room like this one:
0.1,0;0.2,0;0.3,0;...
They are (x,y) locations separated by ;. All of the locations in that list are the free locations in the map. If there is an obstacle in a location, that location won't be in list.
How can I use that list as a map for A* search algorithm?
I've thought to convert that list into a 2D matrix but I don't know what to put inside matrix's cell.
Indeed, it sounds like you can simply convert the list into a 2D matrix by parsing the text file (set x to the character sequence before comma, skip comma, set y to the character sequence before semicolon, skip semicolon, convert x/y to numbers and update matrix accordingly using x/y as indices, etc.).
As for the matrix itself, consider simply a bird's-eye-view of the room, where a '0' in a cell represents a free space, while a '1' represents an obstacle (or the other way around; the values are arbitrary, as long as you use them consistently). And for the A* algorithm, any cell is essentially "adjacent" to the 4 neighboring cells (or whatever movement scheme you are using).
You will have to convert the data to a graph (as in nodes and edges, not as in function plot). In order to do that, you not only need the positions, which translate to nodes (a.k.a. vertices) but the edges. There is an edge between two nodes when you can move from one node directly to the other. In other words, there is no node in between and also no obstacle preventing the movement. Once you have that part down, you can run the A* algorithm on the resulting graph easily.
Steps:
Read and parse input data.
Store data as list of nodes.
Define the requirements for an edge to exist between two nodes.
Create a list of edges with previously defined condition and the nodes.
Run A* on your graph.
Notes:
I won't do the actual work for you because I guess its just homework. Nobody here will hopefully do that.
You can solve each step on its own or even skip it and replace its results using hard-coded values.
You can also skip generating the edges altogether. You just need to adjust the A* algorithm to generate the edges on demand on every node it visits. This may or may not be simpler.

How to find the covering polygon if I know a point all the lines around it

I have a collection of lines in my diagram and I also have a point. What I want is a collection of lines which will together form a polygon through a ordered traversal. I don't need implementation or anything all I want is someone to direct me towards the algorithm I can use.
Similar problem like this have been asked but won't work for me because
One of the common asked problems is that given a polygon I need to find whether the point lies inside it or not but this won't work for me because I don't have any polygons I only have a collection of lines.
the final polygon can be convex too so simply drawing rays on every side from that point and finding intersections won't work I need something more advanced.
Sorry for all the confusion : See this for clarity https://ibb.co/nzbxGF
You need to store your collection of segments inside a suitable data structure. Namely, the chosen data structure should support the concept of faces, as you're looking for a way to find the face in which a given point resides. One such data structure is the Doubly Connected Edge List.
The Doubly Connected Edge List is a data structure that holds a subdivision of the plane. In particular, it contains a record for each face, edge, and vertex of the subdivision. It also supports walking around a face counterclockwise, which allows you to know which segments bound a particular face (such as the face containing the point you're searching for).
You can use a Sweep Line Algorithm to construct the Doubly Connected Edge List in O(nlog(n)+klog(n)) where n is the number of segments and k is the complexity of the resulting subdivision (the total number of vertices, edges, and faces). You don't have to code it from scratch as this data structure and its construction algorithm have already been implemented many times (you can use CGAL's DCEL implementation for example).
With the Doubly Connected Edge List data structure you can solve your problem by applying the approach you've suggested in your post: given an input point, solve the Point in Polygon problem for each face in the Doubly Connected Edge List and return the set of segments bounding the face you've found. However, this approach, while might be good enough for somewhat simple subdivisions, is not efficient for complex ones.
A better approach is to transform the Doubly Connected Edge List into a data structure that is specialized in point location queries: The Trapezoidal Map. This data structure can be constructed in O(nlog(n)) expected time and for any query point the expected search time is O(log(n)). As with the Doubly Connected Edge List, you don't have to implement it yourself (again, you can use CGAL's Trapezoidal Map implementation).

Detecting a cycle given line segments

I'm working on an implementation of the Slab Decomposition algorithm, for point location and I'm stuck in one of its final steps.
I have a list of vertexes and also a list of the vertexes' neighbors (for example, neighbor[0] has all vertexes that are connected to the vertex 0).
I can create the slabs described in the algorithm just fine, but after I detect between which line segments a point is, I don't know how to get the whole partition/cycle/face the point is in.
Basically, I have this
And this is what I want
I could just try to detect all cycles, in a brute force manner, but efficiency is important here. Any idea on how I should approach this problem?
All vertexes and line segments come from an input file, so I could order them in a certain way if it helps with the detection.
Thanks in advance
You could store the planar straight-line graph as a doubly connected edge list. The pertinent feature of the DCEL representation is that the base object be a half-edge (each segment gives rise to two oppositely oriented half-edges, with a tail and a head) with two operations:
DNext(HalfEdge e) - returns the next half-edge with the same head as e
in counterclockwise order around the head
Sym(HalfEdge e) - returns the oppositely oriented half-edge
corresponding to the same edge.
Then you can iterate through the half-edges comprising the face with e = Sym(DNext(e)) until e returns to its starting value.
To compute the DCEL representation in the first place is a matter of sorting the half-edges by angle and then linking them together. There's a way to compare the angles of two half-edges using a 2x2 determinant calculation (avoiding an arctangent, if that's relevant to you).

Combining items into fixed sized groups for k-d tree

I'm using a k-d tree for spacial partitioning in a ray-tracer. I want to combine near-by primitives into fixed-sized groups so the data in each group can be deinterleaved and processed simultaneously using SIMD instructions. What is a good fast algorithm to find the (approximately) smallest fixed-sized groups?
Ideally it would augment the k-d tree building algorithm instead of adding a separate pass, but this is complicated by the fact that the primitives are normally so close together that most primitives will belong to more than one leaf node and I can't have groups with duplicate items because floating point precision errors would mess up shadows and reflections.
I figure I'm far from the first person to try this so a solution already exists, but the most relevant solutions I found from searching the internet for grouping objects deal with point data and variable-sized groups.
One popular way to group objects it to pick a random object, then add the "closest" k objects to a group with it. "Closest" is usually defined to mean giving the smallest surface area for the combined bounding box. You can also use the Hilbert curve distance; either the distance on the 3D curve between the objects' centers, or in 6D space where the bounding boxes become points:
(x_min, y_min, z_min, x_max, y_max, z_max)

Nearest neighbour search in a constantly changing set of line segments

I have a set of line segments. I want to perform the following operations on them:
Insert a new line segment.
Find all line segments within radius R of a given point.
Find all points within radium R1 of a given point.
Given a line segment, find if it intersects any of the existing line segments. Exact intersection point is not necessary(though that probably doesnt simplify anything.)
The problem is algorithms like kd/bd tree or BSP trees is that they assume a static set of points, and in my case the points will constantly get augmented with new points, necessitating rebuilding the tree.
What data-structure/algorithms will be most suited for this situation ?
Edit: Accepted the answer that is the simplest and solves my problem. Thanks everyone!
Maintaining a dynamic tree might not be as bad as you think.
As you insert new points/lines etc into the collection it's clear that you'd need to refine the current tree, but I can't see why you'd have to re-build the whole tree from scratch every time a new entity was added, as you're suggesting.
With a dynamic tree approach you'd have a valid tree at all times, so you can then just use the fast range searches supported by your tree type to find the geometric entities you've mentioned.
For your particular problem:
You could setup a dynamic geometric tree, where the leaf elements
maintain a list of geometric entities (points and lines) associated
with that leaf.
When a line is inserted into the collection it should be pushed onto
the lists of all leaf elements that it intersects with. You can do
this efficiently by traversing the subset of the tree from the root
that intersects with the line.
To find all points/lines within a specified radial halo you first need
to find all leaves in this region. Again, this can be done by traversing
the subset of the tree from the root that is enclosed by, or that
intersects with the halo. Since there maybe some overlap, you need to
check that the entities associated with this set of leaf elements
actually lie within the halo.
Once you've inserted a line into a set of leaf elements, you can find
whether it intersects with another line by scanning all of the lines
associated with the subset of leaf boxes you've just found. You can then
do line-line intersection tests on this subset.
A potential dynamic tree refinement algorithm, based on an upper limit to the number of entities associated with each leaf in the tree, might work along these lines:
function insert(x, y)
find the tree leaf element enclosing the new entitiy at (x,y) based on whatever
fast search algorithm your tree supports
if (number of entities per leaf > max allowable) do
refine current leaf element (would typically either be a bisection
or quadrisection based on a 2D tree type)
push all entities from the old leaf element list onto the new child element
lists, based on the enclosing child element
else
push new entity onto list for leaf element
endif
This type of refinement strategy only makes local changes to the tree and is thus generally pretty fast in practice. If you're also deleting entities from the collection you can also support dynamic aggregation by imposing a minimum number of entities per leaf, and collapsing leaf elements to their parents when necessary.
I've used this type of approach a number of times with quadtrees/octrees, and I can't at this stage see why a similar approach wouldn't work with kd-trees etc.
Hope this helps.
One possibility is dividing your space into a grid of boxes - perhaps 10 in the y-axis and 10 in the x-axis for a total of 100.
Store these boxes in an array, so it's very easy/fast to determine neighboring boxes. Each box will hold a list vector of line segments that live in that box.
When you calculate line segments within R of one segment, you can check only the relevant neighboring boxes.
Of course, you can create multiple maps of differing granularities, maybe 100 by 100 smaller boxes. Simply consider space vs time and maintenance trade-offs in your design.
updating segment positions is cheap: just integer-divide by box sizes in the x and y directions. For example, if box-size is 20 in both directions and your new coordinate is 145,30. 145/20==7 and 30/20==1, so it goes into box(7,1), for a 0-based system.
While items 2 & 3 are relatively easy, using a simple linear search with distance checks as each line is inserted, item 4 is a bit more involved.
I'd tend to use a constrained triangulation to solve this, where all the input lines are treated as constraints, and the triangulation is balanced using a nearest neighbour rather than Delaunay criterion. This is covered pretty well in Triangulations and applications by Øyvind Hjelle, Morten Dæhlen and Joseph O'Rourkes Computational Geometry in C Both have source available, including getting sets of all intersections.
The approach I've taken to do this dynamically in the past is as follows;
Create a arbitrary triangulation (TIN) comprising of two triangles
surrounding the extents (current + future) of your data.
For each new line
Insert both points into the TIN. This can be done very quickly by
traversing triangles to find the insertion point, and replacing the
triangle found with three new triangles based on the new point and
old triangle.
Cut a section through the TIN based on the two end points, keeping a
list of points where the section cuts any previously inserted lined.
Add the intersection point details to a list stored against both
lines, and insert them into the TIN.
Force the inserted line as a constraint
Balance all pairs of adjacent triangles modified in the above process
using a nearest neighbour criterion, and repeat until all triangles
have been balanced.
This works better than a grid based method for poorly distributed data, but is more difficult to implement. Grouping end-point and lines into overlapping grids will probably be a good optimization for 2 & 3.
Note that I think using the term 'nearest neighbour' in your question is misleading, as this is not the same as 'all points within a given distance of a line', or 'all points within a given radius of another point'. Nearest neighbour typically implies a single result, and does not equate to 'within a given point to point or point to line distance'.
Instead of inserting and deleting into a tree you can calculate a curve that completely fills the plane. Such a curve reduce the 2d complexity to a 1d complexity and you would be able to find the nearest neighbor. You can find some example like z curve and hilbert curve. Here is a better description of my problem http://en.wikipedia.org/wiki/Closest_pair_of_points_problem.

Resources