Boundary markers of nodes and faces in Tetgen - finite-element-analysis

Let's say I create a .poly detailing the information of the my domain geometry.
I also add node boundary markers and face boundary markers.
Question 1:
Do I have to be consistent between the boundary markers of nodes and faces? I mean, if a node belongs to a face with boundary marker 1, do I have to label it with 1 too?
Question 2:
In the case there's no need to be consistent, what will happen when I create the mesh? Specifically talking, which boundary markers will appear in .face and .node files? The boundary markers of the faces or the nodes specified in the .poly file? How should I proceed to propagate the boundary markers in a good way
(I'm doing Finite element method, so I want to know which are my Dirichlet and Neumann faces)?

Dirichlet boundary conditions are associated with nodal degrees of freedom; Neumann boundary conditions describe fluxes/tractions on element faces.
Dirichlet boundary conditions will be specified at nodes. The node ids are pertinent here.
Neumann boundary conditions are specified on element faces.
They are separate by definition and necessity. I am not sure about the Tetgen generation tool, but my guess is that node and element numbering should not be affected by your boundary conditions.

Related

are contour data (X,Y) ordered in a connected clockwise path in matplotlib?

As in the title:
pl = plt.contour(X,Y,Z,levels=[0])
paths = pl.allsegs
I wonder how are the data points in paths ordered. Specifically is it oriented clockwise, counterclockwise w.r.t. a guiding center?
The reason I am asking is because matplotlib.pyplot is unaware of torus topology, where edges are identified as the same. connected paths on a torus can look disconnected on an open ended 2D space. I would like to make use of the path datasets to glue together seemingly disconnected segments onto a torus manifold.
I resolved this problem by the following steps:
make use of the torus structure, i.e., Z[0,:] = Z[N,:], Z[:,0] = Z[:,M], where (N,M) are linear dimensions of the matrix.
find allsegs from contour plot for a given level z0:
pl = plt.contour(X,Y,Z,levels=[z0])
segs = pl.allsegs[0]
segs[i] contains the coordinates of a given contour whose two end points either: (1) are the same, then segs[i] is a closed contour in the domain set by X and Y. (2) are different and therefore must terminate at either of the four edges of the domain. In this case, there must exist at least another open contour whose end points pair-up with the current open contour. This pair identification is achieved by calculating their distance on a torus, which is defined as the smallest of |r1-r2|, |r1-r2 +/- period_along_x|, |r1-r2 +/- period_along_y|
ultimately the numerical algorithm boils down to identifying closed contours as well as identifying pairs of matching end points satisfying torus topology.
Three example solutions are shown in the attached figure.
Four open contours, but it is one contour on a torus, where end points are identified as pairs by color
Two closed contours, where two end points of each contour are identical

CGAL Mean_curvature_flow_skeletonization contract_until_convergence function produces branches that does not exist in input polygon

I use contract_until_convergence function from CGAL Mean_curvature_flow_skeletonization to produce skeleton from input polygon.
https://doc.cgal.org/latest/Surface_mesh_skeletonization/classCGAL_1_1Mean__curvature__flow__skeletonization.html
In some cases the skeleton creates branches (see top of the image above, skeleton in red color) that does not exist in input polygon. Is there some parameters to set to prevent this ?
using Skeletonization = CGAL::Mean_curvature_flow_skeletonization<Polyhedron>;
Skeletonization mean_curve_skeletonizer(polyhedron);
mean_curve_skeletonizer.contract_until_convergence();
There are two parameters controlling the quality of the skeleton:
quality_speed_tradeoff()
medially_centered_speed_tradeoff()
Also one thing that affect the skeleton is the sampling of the input surface that is used to compute Voronoi poles. In the original papers, it is said: Given a sufficiently good sampling, the Voronoi poles [ACK00] form a provably convergent sampling of the medial axis.
[ACK00]AMENTAN., CHOIS., KOLLURIR. K.: The powercrust, unions of balls, and the medial axis transform. Computational Geometry: Theory and Applications 19(2000), 127–153.3
You can use the function isotropic_remeshing with a sufficiently small target edge length to improve the Voronoi pole computation.

How to map the node identities of my resulting surface mesh generated from Poisson_surface_reconstruction_3 into my starting point sets?

thanks for reading this question. My title is basically what I'm trying to achieve. I did a poisson surface mesh generation using Poisson_surface_reconstruction_3(cgal). I can't figure out how to map the node identities of my resulting surface mesh into my starting point sets?
The output of my poisson surface generation is produced by the following lines:
CGAL::facets_in_complex_2_to_triangle_mesh(c2t3, output_mesh);
out << output_mesh;
In my output file, there are some x y z coordinates, followed by a set of 3 integers each line, I think they indicates which nodes form a delaunay triangle. The problem is that the output points do not correspond to my initial point set, since not any x y z value match to any of my original points. Yet I'm trying to figure out which points are forming a delaunay triangles in my original point set.
Could someone suggest me how can I do this in cgal?
Many thanks.
The poisson recontruction algorithm consist in meshing an implicit function that somehow fits you input points. In practice, it means that you input point will no belong to the set of points of the output surface, and won't even lie exactly on triangles of the output surface. However, they should not be too far from the output surface (except if you have some really sparse sampling parts).
What you can do to locate your input points with the output surface is to use the function closest_point_and_primitive() from the AABB-tree class.
Here is an example of how to build the tree from a mesh.

Is polygon operation in CGAL working with polygon that has duplicated edge?

I have a polygon as such:
{0}, {1}, {2}, {3},... denote the sequence of the points on the polygon.
I wonder whether CGAL polygon boolean set-operations work with polygon as such?
From the user manual, the input polygon must be simple or relatively simple in order for the CGAL polygon boolean set-operations to work:
A relatively simple polygon allows vertices with a degree >2, but all
of its edges are disjoint in their interior. Furthermore, it must be
an orientable polygon. Namely when it is inserted into an arrangement
and its outer boundary is traversed, the same face is adjacent to all
of the halfedges (no crossing over any curve during the traversal).
Note that while polygon C has the same curves as polygon B, traversal
of the curves leads to crossing over a previously traversed curve, and
is therefore neither simple nor relatively simple.
Not sure what it really means, but my guess is that the polygon is still ( at least) relatively simple, and hence the CGAL polygon boolean operation still works... am I right?
If you look at the condition for a valid polygon in the user manual, you'll see that the input polygon must be simple. Yours is not since you have a duplicated edge.

Search optimization problem

Suppose you have a list of 2D points with an orientation assigned to them. Let the set S be defined as:
S={ (x,y,a) | (x,y) is a 2D point, a is an orientation (an angle) }.
Given an element s of S, we will indicate with s_p the point part and with s_a the angle part. I would like to know if there exist an efficient data structure such that, given a query point q, is able to return all the elements s in S such that
(dist(q_p, s_p) < threshold_1) AND (angle_diff(q_a, s_a) < threshold_2) (1)
where dist(p1,p2), with p1,p2 2D points, is the euclidean distance, and angle_diff(a1,a2), with a1,a2 angles, is the difference between angles (taken to be the smallest one). The data structure should be efficient w.r.t. insertion/deletion of elements and the search as defined above. The number of vectors can grow up to 10.000 and more, but take this with a grain of salt.
Now suppose to change the above requirement: instead of using the condition (1), let's request all the elements of S such that, given a distance function d, we want all elements of S such that d(q,s) < threshold. If i remember well, this last setup is called range-search. I don't know if the first case can be transformed in the second.
For the distance search I believe the accepted best method is a Binary Space Partition tree. This can be stored as a series of bits. Each two bits (for a 2D tree) or three bits (for a 3D tree) subdivides the space one more level, increasing resolution.
Using a BSP, locating a set of objects to compare distances with is pretty easy. Just find the smallest set of squares or cubes which contain the edges of your distance box.
For the angle, I don't know of anything. I suppose that you could store each object in a second list or tree sorted by its angle. Then you would find every object at the proper distance using the BSP, every object at the proper angles using the angle tree, then do a set intersection.
You have effectively described a "three dimensional cyclindrical space", ie. a space that is locally three dimensional but where one dimension is topologically cyclic. In other words, it is locally flat and may be modeled as the boundary of a four-dimensional object C4 in (x, y, z, w) defined by
z^2 + w^2 = 1
where
a = arctan(w/z)
With this model, the space defined by your constraints is a 2-dimensional cylinder wrapped "lengthwise" around a cross section wedge, where the wedge wraps around the 4-d cylindrical space with an angle of 2 * threshold_2. This can be modeled using a "modified k-d tree" approach (modified 3-d tree), where the data structure is not a tree but actually a graph (it has cycles). You can still partition this space into cells with hyperplane separation, but traveling along the curve defined by (z, w) in the positive direction may encounter a point encountered in the negative direction. The tree should be modified to actually lead to these nodes from both directions, so that the edges are bidirectional (in the z-w curve direction - the others are obviously still unidirectional).
These cycles do not change the effectiveness of the data structure in locating nearby points or allowing your constraint search. In fact, for the most part, those algorithms are only slightly modified (the simplest approach being to hold a visited node data structure to prevent cycles in the search - you test the next neighbors about to be searched).
This will work especially well for your criteria, since the region you define is effectively bounded by these axis-defined hyperplane-bounded cells of a k-d tree, and so the search termination will leave a region on average populated around pi / 4 percent of the area.