|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.jcae.mesh.amibe.algos2d.Initial
public class Initial
Performs an initial Delaunay triangulation.
This algorithm is invoked to perform the initial triangulation of
each CAD patch, after the discretization of edges has been performed.
Wires of this patch are processed in turn. All nodes belonging to
discretization of these edges are projected onto this 2D patch
and collected into a list. These nodes are boundary nodes, and
all other nodes will be inserted in the interior domain. A bounding
box enclosing all these nodes in the 2D space is computed, and
a KdTree
instance can then be
initialized by
Mesh.resetKdTree(double [], double [])
.
Some checks have been added to remove tiny edges and make sure that boundary is closed. But this is a hack, the right solution is to analyze the overall CAD structure and make sure that edges are well connected and not too small. In particular, the tolerance on vertex location should be used to remove vertices which may be duplicates.
A first triangle is created by iterating over the list of boundary nodes
to find three vertices which are not aligned. The outer domain is also
triangulated; Mesh.outerVertex
is a vertex at infinite, and three
outer triangles are created by joining this vertex to vertices of the
first triangle. With this trick, there is no need to have special
cases when vertices are inserted outside the convex hull of already inserted
vertices, and triangle location always succeed. If these outer triangles
did not exist, we would have to triangulate the convex hull of nodes.
Boundary nodes are then inserted iteratively. For the moment, an Euclidian
2D metric is used because a 3D metric will not help on a very rough
triangulation. The nearest vertex already inserted in the mesh is retrieved
with KdTree.getNearestVertex(Mesh, Vertex)
.
It has a reference to a triangle containing this vertex. From this starting
point, we search for the Triangle
containing this boundary node by
looking for adjacent triangles into the right direction. This
Triangle
is splitted into three triangles (even if the vertex
is inserted on an edge), and edges are swapped if they are not Delaunay.
(This criterion also applied with our Euclidian 2D metric)
When all boundary nodes are inserted, an unconstrained Delaunay mesh has
been built. The list of boundary nodes computed previously gives a list of
boundary edges, which needs to be enforced. This is performed by
Mesh2D.forceBoundaryEdge(Vertex2D, Vertex2D, int)
; the segments which
intersect the enforced edge are swapped. The AbstractHalfEdge.BOUNDARY
attribute is set on these edges (and on matte edges).
We know that the Triangle
bound to Mesh.outerVertex
is an
outer triangle. Triangles adjacent through a boundary edge are interior
triangles, and triangles adjacent through non-boundary edges are also
outer triangles. All triangles of the mesh are visited, and outer
triangles are tagged with the AbstractHalfEdge.OUTER
attribute.
If an inconsistency is found (for instance a boundary edge seperate
two outer triangles), InitialTriangulationException
is
raised. This means that boundary was invalid, eg. it is not closed
or intersects itself.
This detection of broken boundaries could be improved by taking
advantage of some OpenCascade features, like the detection of
self-intersection and object tolerance.
It is important to note that triangles in holes have their
OUTER
attribute set, but are not linked to
Mesh.outerVertex
. So this attribute is the only safe way to
detect outer triangles. As outer triangles are not removed,
vertex location can still be performed as if the domain was
convex. All subsequent 2D algorithms should consider these points.
This is very different when remeshing 3D meshes; in such a case,
boundary edges are detected because they have only one incident
face. An outer triangle is then added by connecting end points to
Mesh.outerVertex
, but outer triangles are not connected together.
Mesh domain is not convex, but that does not matter because 3D
algorithms do not require vertex location.
After this initial triangulation has been performed, it is time to
add interior vertices to fulfill user's requirements. The Euclidian
2D metric is replaced by the 2D Riemannian metric
Metric2D
induced by surface local
properties and user constraints. But current triangles can cross
the whole surface, so metrics of its vertices may be very different.
There are two problems:
In order to improve accuracy, Frédéric Hecht advised to recursively
split segments when metrics at end points are very different. This
has been implemented in
Calculus3D.distance(Vertex2D, Vertex2D)
but did not give good results. Now that the whole process works much
better, this issue could be investigated again.
About inverted triangles, he also explained that we do not have to care if large triangles are inverted in 3D, because they will be fixed naturally when being splitted up.
The current implementation begins with swapping edges (by calling
VirtualHalfEdge2D.checkSmallerAndSwap(org.jcae.mesh.amibe.patch.Mesh2D)
) if the opposite diagonal
is smaller. This method did improve some test cases, but is
certainly useless with the current meshing process because it has
been dramatically improved since these tests have been performed.
The following steps are then performed:
Insertion
) to
have a mesh with target size of 16.ConstraintNormal3D
). If triangle
inversion gives better result, edges are swapped.
Constructor Summary | |
---|---|
Initial(Mesh2D m,
MeshTraitsBuilder mtb,
MMesh1D m1d)
Creates a Initial instance. |
|
Initial(Mesh2D m,
MeshTraitsBuilder mtb,
MMesh1D m1d,
java.util.Collection<MNode1D> innerNodes)
A constructor to insert constrain some points in the mesh |
|
Initial(Mesh2D m,
MeshTraitsBuilder mtb,
Vertex2D[] boundaryNodes,
java.util.Collection<MNode1D> innerNodes)
A constructor for Bora, which use it's own Mesh1D |
Method Summary | |
---|---|
void |
compute()
Launch method to mesh a surface. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public Initial(Mesh2D m, MeshTraitsBuilder mtb, MMesh1D m1d)
Initial
instance.
m
- the data structure in which the mesh will be stored.m1d
- 1D meshpublic Initial(Mesh2D m, MeshTraitsBuilder mtb, MMesh1D m1d, java.util.Collection<MNode1D> innerNodes)
public Initial(Mesh2D m, MeshTraitsBuilder mtb, Vertex2D[] boundaryNodes, java.util.Collection<MNode1D> innerNodes)
Method Detail |
---|
public void compute()
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |