function "buildConsecutiveListOfVertices()" of the source code : some errors may occur
Hi, I have a model (Figure 1) and zoom in on this model (Figure 2) finds that the two curves here are not connected. But actually the connection here is correct, the endpoints of the two curves are the same points in Figure 2.
Then I trangulated this model with gmsh-4.8.4 and it worked, but the same model with gmsh-4.11.1 and it failed. So I compared the source code of both versions and found that the function "buildConsecutiveListOfVertices()" in function "meshGeneratorPeriodic()" is different. What causes the difference in the meshing results is the difference in the distance function. The following code block belongs to version 4.8.4.
// this code block is in meshGFace.cpp
if(MYDEBUG) printf("Followed by edge = %d\n", (*it).ge->tag());
SPoint2 first_coord = mesh1d[0];
double d = -1, d_reversed = -1, d_seam = -1, d_seam_reversed = -1;
d = dist2(last_coord, first_coord);
if(MYDEBUG)
printf("%g %g dist = %12.5E\n", first_coord.x(), first_coord.y(), d);
SPoint2 first_coord_reversed = mesh1d_reversed[0];
d_reversed = dist2(last_coord, first_coord_reversed);
if(MYDEBUG)
printf("%g %g dist_reversed = %12.5E\n", first_coord_reversed.x(),
first_coord_reversed.y(), d_reversed);
if(d < tol && d < d_reversed) {
coords.clear();
coords = mesh1d;
found = GEdgeSigned(1, ge);
unordered.erase(it);
goto Finalize;
}
if(d_reversed < tol) {
coords.clear();
coords = mesh1d_reversed;
found = (GEdgeSigned(-1, ge));
unordered.erase(it);
goto Finalize;
}
The following code block belongs to version 4.11.1.
// this code block is in meshGFace.cpp
double dist1 = coords.back().distance(p.front());
double dist2 = coords.back().distance(p_rev.front());
if(!seam) {
if(dist1 < dist2 && dist1 < tol) {
coords.pop_back();
coords.insert(coords.end(), p.begin(), p.end());
verts.pop_back();
verts.insert(verts.end(), v.begin(), v.end());
}
else if(dist2 < dist1 && dist2 < tol) {
coords.pop_back();
coords.insert(coords.end(), p_rev.begin(), p_rev.end());
verts.pop_back();
verts.insert(verts.end(), v_rev.begin(), v_rev.end());
}
else{
Msg::Debug("Distances (%g, %g) in parametric space larger than "
"tolerance (%g) between end of curve %d and "
"begining of curve %d...", dist1, dist2, tol,
signedEdges[i - 1].getEdge()->tag(), ge->tag());
if(initial_dir == 0){
Msg::Debug("... will try with alternate initial orientation");
coords.clear();
verts.clear();
break;
}
else{
Msg::Debug("... will try with larger tolerance");
return false;
}
}
The former distance function "dist2()" is not squared and the latter distance function "distance()" is squared. The former just satisfies the smaller of the given tolerances, while the later only satisfies the largest tolerance, 1e-1. When the largest tolerance is satisfied, there is an error in connecting the endpoints of the two curves, as shown in Figure 5. Point 1 should have been connected to point 2, but due to the direction of the curve the distance between point 3 and point 1 was calculated first, which just happened to satisfy the given tolerance, resulting in the incorrect connection of point 3 to point 1. This will result in the subsequent determination of this curve as a self-intersecting curve and fail to mesh.
Perhaps both endpoints of the curve need to be compared and the one with the smallest distance chosen as the connection point to prevent this error? Hope you can give a better solution, thank you very much! The model is here. model.stp