## Summary of Changes
This PR fixes the error reported in issue #781. The main two changes
are:
- in `Refine_edges.h`: allow the refinement point of a constrained edge
to be an existing close encroaching vertex,
- in `Refine_faces.h`: skip tiny bad faces when their bbox are smaller
than a few ulp.
## Release Management
* Affected package(s): Triangulation_2, Mesh_2
* Issue(s) solved (if any): fix#781
* Feature/Small Feature (if any):
* Link to compiled documentation (obligatory for small feature) [*wrong
link name to be changed*](httpssss://wrong_URL_to_be_changed/Manual/Pkg)
* License and copyright ownership: maintenance by GeometryFactory, now
copyright change
The error was:
```plain
Before conforming Gabriel: 2 vertices.
Smallest squared distance between constraint endpoints: 0.26281523970953841
terminate called after throwing an instance of 'CGAL::Precondition_exception'
what(): CGAL ERROR: precondition violation!
Expr: f->neighbor(i) != Face_handle() && f->dimension() >= 1
File: /home/lrineau/Git/cgal-master/TDS_2/include/CGAL/Triangulation_data_structure_2.h
Line: 243
```
The bug was reproducible with:
```shell
/path/to/build/test/Mesh_2/test_mesh_obj Mesh_2/test/Mesh_2/triwild-10070-min2.obj
```
The fix is simple: do not scan the triangulation. In dimension 1, every segment is Delaunay.
The bug was reproduced by
```shell
/path/to/build/test/Mesh_2/test_mesh_obj Mesh_2/test/Mesh_2/triwild-10070-min1.obj
```
The log of the error, with all the debug options of Mesh_2 was:
```plain
Before conforming Gabriel: 4 vertices.
Smallest squared distance between constraint endpoints: 0.010522898628224919
edge #1= 453.57378188125 445.0501073328125 -- #3= 454.05836694375 445.48749872343745 is encroached by #2= 453.77453855000005 445.23131233749996
add_constrained_edge_to_be_conformed(#1= 453.57378188125 445.0501073328125, #3= 454.05836694375 445.48749872343745)
edge #2= 453.77453855000005 445.23131233749996 -- #0= 453.49763280000002 444.98137439999999 is encroached by #1= 453.57378188125 445.0501073328125
add_constrained_edge_to_be_conformed(#2= 453.77453855000005 445.23131233749996, #0= 453.49763280000002 444.98137439999999)
split_cluster_point(454.05836694375 445.48749872343745 , 453.57378188125 445.0501073328125)
reduced: 0
result: 453.77453855000005 445.23131233750001
edge #1= 453.57378188125 445.0501073328125 -- #3= 454.05836694375 445.48749872343745 is encroached by #2= 453.77453855000005 445.23131233749996
Refine_edges_with_clusters::refinement_point_impl(Edge: (#1= 453.57378188125 445.0501073328125, #3= 454.05836694375 445.48749872343745) = 453.77453855000005 445.23131233750001
(453.77453855000005 445.23131233750001) accepted
on edge, insert(453.77453855000005 445.23131233750001): 3 boundary edges in the zone
inserted new vertex #4= 453.77453855000005 445.23131233750001
update_clusters
va_has_a_cluster=0
vb_has_a_cluster=1
clusters.size()=2
E edge #3= 454.05836694375 445.48749872343745 -- #2= 453.77453855000005 445.23131233749996 is encroached by #4= 453.77453855000005 445.23131233750001
add_constrained_edge_to_be_conformed(#3= 454.05836694375 445.48749872343745, #2= 453.77453855000005 445.23131233749996)
edge #1= 453.57378188125 445.0501073328125 -- #4= 453.77453855000005 445.23131233750001 is encroached by #2= 453.77453855000005 445.23131233749996
add_constrained_edge_to_be_conformed(#1= 453.57378188125 445.0501073328125, #4= 453.77453855000005 445.23131233750001)
Cluster at #3= 454.05836694375 445.48749872343745 is updated.
vm: #4= 453.77453855000005 445.23131233750001
reduction: 1
min_sq_len: 0.1461900214383674
clusters.size() after update_cluster=2
split_cluster_point(453.49763280000002 444.98137439999999 , 453.77453855000005 445.23131233749996)
reduced: 0
result: 453.64993096249998 445.11884026562501
edge #2= 453.77453855000005 445.23131233749996 -- #0= 453.49763280000002 444.98137439999999 is encroached by #1= 453.57378188125 445.0501073328125
Refine_edges_with_clusters::refinement_point_impl(Edge: (#2= 453.77453855000005 445.23131233749996, #0= 453.49763280000002 444.98137439999999) = 453.64993096249998 445.11884026562501
(453.64993096249998 445.11884026562501) accepted
on edge, insert(453.64993096249998 445.11884026562501): 0 boundary edges in the zone
terminate called after throwing an instance of 'CGAL::Precondition_exception'
what(): CGAL ERROR: precondition violation!
Expr: i >= 0 && i < 3
```
The following edge `(#1, #3)` is encroached by the vertex `#2`:
```plain
edge #1= 453.57378188125 445.0501073328125 -- #3= 454.05836694375 445.48749872343745 is encroached by #2= 453.77453855000005 445.23131233749996
```
The inserted vertex `#4= 453.77453855000005 445.23131233750001` is the projection of the vertex `#2= 453.77453855000005 445.23131233749996` (rules to refine a segment part of a cluster.
The distance between `#2` and its projection `#4` is:
- `0` on the x-axis,
- `ulp(v2.y()))` on the y-axis.
... and then, Mesh_2 cannot do anything with that.
The fix is to implement a snapping strategy: if the encroaching vertex is close enough, then chose it be the refinement point of the encroached segment. "Close enough" means:
- create tiny `Bbox_2` centered on the encroaching vertex, with snaps equal to 8 ulp on both axis,
- if that tiny bbox intersects the encroached segment, then the refinement is the encroaching vertex.
- remove all mentions of `Edge` and `Constraint`
- `Subconstraint_iterator` is renamed `Subconstraint_and_contexts_iterator` (because of its value type)
- a new `Subconstraint_iterator`, with value type `Subconstraint`
- a few unused/untested and uncompilable functions are removed from the code
- a lot of internal renamings
== Breaking changes ==
For `Constrained_triangulation_plus_2`, there are a few breaking changes...
- The value type of `subconstraints_begin()`, `subconstraints_end()`, of the range `subconstraints()` has changed to `Subconstraint` (a simple `std::pair` of vertex handles). That is actually a kind of bug-fix, because it was documented as such in the user manual.
- The new member functions `subconstraints_and_contexts_begin()`, `subconstraints_and_contexts_end()`, `subconstraints_and_contexts()` are created get the old value type (`std::pair<const Subconstraint, std::list<Context>*>`).
- A few range types have changed from `CGAL::Iterator_range<It>` to `unspecified_type`, for efficiency reasons.
- Doc fixes.
== Determinism ==
Even if it was not documented, the range `subconstraints()` is deterministic (used by Mesh_2), and `subconstraints_and_contexts()` is not.