Commit Graph
371 Commits
Author SHA1 Message Date
Sebastien Loriot f60daf05e4 Mesh_2: fix degenerate cases (#9290)
## 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
2026-02-12 15:01:59 +01:00
Laurent Rineau 1e2363810b Mesh_2: fix a bug with a cdt of dimension()==1
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.
2026-02-06 18:18:52 +01:00
Laurent Rineau 13199b1af1 better debug messages 2026-02-06 17:27:50 +01:00
Laurent Rineau 93fa24e252 Mesh_2: fix bug with Mesh_2/test/Mesh_2/triwild-10070-min1.obj
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.
2026-02-06 16:59:37 +01:00
Laurent Rineau bb9e0e96f2 better debug output
Now CGAL_MESH_2_DEBUG_BAD_EDGES shows the encroaching vertex.
2026-02-05 17:17:10 +01:00
Laurent Rineau e34cd728ac remove a duplicate assertion
The same assertion was already tested in `push_in_bad_faces()`.
2026-02-05 17:03:13 +01:00
Laurent Rineau 7d3efe9db8 cosmetic change: use oformat for better debug output 2026-02-05 12:19:23 +01:00
Andreas Fabri b65a62d63e Fix fixture 2026-02-04 07:11:39 +00:00
Andreas Fabri aad557cf69 Add overload of read_OBJ() 2026-02-02 15:12:34 +00:00
Laurent Rineau d5ea093082 fix for windows.h 2026-01-30 18:16:39 +01:00
Laurent Rineau 035edd52a4 change snap distance: from 4 ulp to 16 ulp 2026-01-28 16:07:54 +01:00
Andreas Fabri efcc227871 Half-space -> Halfspace 2026-01-23 10:49:04 +00:00
Laurent Rineau 2adca86eef fix warnings 2026-01-22 11:43:20 +01:00
Laurent Rineau 56076d6e9a fix a compilation error 2026-01-21 11:50:39 +01:00
Laurent Rineau dafcd62608 fix included headers 2026-01-21 10:42:41 +01:00
Laurent Rineau 7626f5bc14 fix comments
[skip ci]
2026-01-21 10:36:46 +01:00
Laurent Rineau bfd10b95b7 fix included headers 2026-01-21 10:13:18 +01:00
Laurent Rineau c4caded301 fix warnings about headers 2026-01-20 21:14:02 +01:00
Laurent Rineau 915f5e95c1 code cleanup 2026-01-20 21:12:16 +01:00
Laurent Rineau a48e7ee74d Mesh_2: ignore microscopic bad faces 2026-01-20 21:08:12 +01:00
Laurent Rineau 3d7080aaf5 fix warnings 2026-01-20 18:21:23 +01:00
Laurent Rineau 2ee9b47a16 better debug messages 2026-01-20 17:58:58 +01:00
Laurent Rineau 6626a536ae Refine_edges refinement point: allow snapping to an existing vertex 2026-01-20 17:13:55 +01:00
Sébastien Loriot c0de2cf4a2 move to T2
try fixing CI
2025-08-29 09:55:55 +02:00
Sébastien Loriot f6bfc3bf96 update license 2025-08-28 10:50:09 +02:00
Sébastien Loriot 96e67f3048 change to Triangulation_2 license 2025-08-27 20:49:34 +02:00
Andreas Fabri 2bdeff8687 counter-clockwise -> counterclockwise 2025-05-15 07:41:00 +01:00
Andreas Fabri bd64af08fd Mesh_2: make lloyd_optimize_mesh_2() deterministic 2025-03-04 16:32:15 +00:00
Sébastien Loriot 043becfe7f Merge pull request #8273 from lrineau/CGAL-followup_PR_8170-lrineau
Improvement backports from CDT_3 branch (Follow-up to PR #8170)
2025-02-12 19:43:35 +01:00
Laurent Rineau fad5e30a54 initialize to -2, to use the debugging assertions 2025-01-31 18:09:07 +01:00
Sébastien Loriot eb0da467ed always init time_stamp to -1 2025-01-24 11:08:34 +01:00
Laurent Rineau eafa97a862 major cleanup of Polyline_constraint_hierarchy_2
- 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.
2025-01-13 17:06:58 +01:00
Laurent Rineau 93ac1845fa CDT_plus_2 hierarchy: add Edge_iterator, that is deterministic
That uses Boost.STLInterfaces from Boost >= 1.74.
2025-01-13 11:36:05 +01:00
Laurent Rineau b12625f169 fix an error detected by UBSAN 2025-01-08 21:13:43 +01:00
Laurent Rineau aaac2c2dc1 Merge remote-tracking branch 'cgal/master' into pr/lrineau/8273 2025-01-08 11:34:54 +01:00
albert-github dd02af92a2 issue #8515 Spelling mistakes found checking en-GB to en-US
Spelling corrections, `en-GB` -> `en-US`
2024-10-05 11:28:29 +02:00
Laurent Rineau 82b53596fd Mesh_2: sort the sequence tr.subconstraints_begin(), tr.subconstraints_end() 2024-06-13 16:31:32 +02:00
Laurent Rineau 120a8c14a3 add missing includes
detected with gcc 14.0.1 from Fedora 40
2024-03-26 11:29:51 +01:00
Laurent Rineau 1d29a75c9a iformat/oformat are in CGAL::IO
The calls without the `IO::` namespace are deprecated.
2023-09-25 16:09:41 +02:00
Sébastien Loriot f936680600 Merge remote-tracking branch 'cgal/master' into HEAD 2023-06-15 18:48:39 +02:00
Mael 532b82cb9b Merge branch 'master' into P3M3-Undocumented_polyhedral_domain_example-GF 2023-05-04 17:28:47 +02:00
Laurent Rineau d2bc415a15 Merge pull request #6950 from lrineau/CGAL-allow_Epick_with_float-GF
Simple_precision_epick: an Epick-like kernel with float as FT
2023-05-04 16:37:17 +02:00
Sébastien Loriot ea62c316ae boost::lambda -> c++11 lambda 2023-04-23 22:37:07 +02:00
Mael Rouxel-Labbé 9d9a51731a Fix typo 2023-02-09 23:27:01 +01:00
Sébastien Loriot 9e137bca24 Merge 'cgal/master' 2023-01-31 12:26:55 +01:00
Mael 8f703b54cb Merge branch 'master' into P3M3-Undocumented_polyhedral_domain_example-GF 2023-01-27 21:48:32 +01:00
Mael Rouxel-Labbé 7910d82c6c Misc minor changes 2022-12-01 12:34:50 +01:00
Laurent Rineau 36cf65d327 FT as return type is enforced by the base class 2022-11-22 16:39:08 +01:00
albert-github 3674c937f7 spelling corrections
Some spelling corrections (Directories starting with `M`-` N`),
some backward work
some forward work
2022-11-15 15:21:01 +01:00
albert-github 45478184de spelling corrections
Some spelling corrections (Directories starting with `E`-` L`),
some backward work
some forward work
2022-11-15 13:39:40 +01:00