Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ease drawing of SDG duals #7976

Merged
merged 2 commits into from
Jan 24, 2024
Merged

Ease drawing of SDG duals #7976

merged 2 commits into from
Jan 24, 2024

Conversation

afabri
Copy link
Member

@afabri afabri commented Jan 11, 2024

Summary of Changes

Issue #7973 mentions improvements to do on the undocumented class Parabola_segment_2. To get started we make it a struct. Mael will add an example with some better drawing implementation.

Release Management

  • Affected package(s): Segment_Delaunay_graph_2
  • License and copyright ownership: unchanged

@afabri afabri requested a review from MaelRL January 11, 2024 09:48
@afabri afabri added this to the 6.0-beta milestone Jan 11, 2024
@MaelRL MaelRL changed the title Parabola_segment_2: turn it into a struct Ease drawing of SDG duals Jan 11, 2024
@MaelRL
Copy link
Member

MaelRL commented Jan 11, 2024

@Yvee1 I have added in 958eabe a comprehensive example on how to generate a cropped dual of a generic segment Delaunay graph, using both an inexact kernel during the computation (for speed) and an exact kernel with exact square roots in the construction of the dual (for precision of the positions). It might be of interest to you, or at least to see how you can extract your undiscretized parabolas.

Here is some example:
Screenshot from 2024-01-11 12-10-12

Let me know if you have any question.

@gdamiand
Copy link
Member

@MaelRL The pull request #6967 changes many things about drawing functions. It is maybe interesting to base this pr on the new version?

@MaelRL
Copy link
Member

MaelRL commented Jan 11, 2024

It doesn't draw per se or use basic viewers; it's more like "print": it only creates a list of segments that can e.g. be read by the polyhedron demo.

But thanks for checking :)

@Yvee1
Copy link

Yvee1 commented Jan 11, 2024

Thanks for the example. It is not clear to me though why you would want to use an exact kernel for drawing, could you elaborate on that? Also you seem to still discretize the parabolic segments.

In case it is of any help to others, and to make my issue clearer: my temporary solution was to rewrite the draw_dual_edge function so that it passes the parabolic segment to the stream as below.

template <class Stream,
          class K,
          class Gt  = CGAL::Segment_Delaunay_graph_traits_2<K>,
          class SDG = CGAL::Segment_Delaunay_graph_2<Gt>,
          class ST = CGAL::Segment_Delaunay_graph_storage_traits_2<Gt>,
          class D_S = CGAL::Triangulation_data_structure_2<CGAL::Segment_Delaunay_graph_vertex_base_2<ST>, CGAL::Segment_Delaunay_graph_face_base_2<Gt>>>
Stream& draw_dual_edge(const SDG& dg, typename D_S::Edge e, Stream& str)
{
	typename Gt::Line_2    l;
	typename Gt::Segment_2 s;
	typename Gt::Ray_2     r;
	CGAL::Parabola_segment_2<Gt> ps;

	CGAL::Object o = dg.primal(e);

	if (CGAL::assign(l, o))   str << l;
	if (CGAL::assign(s, o))   str << s;
	if (CGAL::assign(r, o))   str << r;
	if (CGAL::assign(ps, o))  str << ps;

	return str;
}

Then I can handle it as follows.

VoronoiDrawer& VoronoiDrawer::operator<<(const CGAL::Parabola_segment_2<Gt>& p) {
	auto dir = p.line();
	auto focus = p.center();

	// Roundabout way to obtain start and end of parabolic segment because they are protected
	std::vector<Gt::Point_2> pts;
	p.generate_points(pts, Gt::FT(1000000));
	auto start = pts.front();
	auto end = pts.back();

	auto control = CGAL::circumcenter(focus, dir.projection(start), dir.projection(end));

	// Draw quadratic Bezier curve from start to end with control as control point

	return *this;
}

@MaelRL
Copy link
Member

MaelRL commented Jan 11, 2024

Thanks for the example. It is not clear to me though why you would want to use an exact kernel for drawing, could you elaborate on that?

You can divide CGAL kernel functors into two categories: predicates (these are "yes"/"no" queries such as "is this geometry object intersecting that other geometric object?") and constructions (operations in which a new geometric entity appears).

To build the correct SDG_2, you can use only exact predicates because the sites are given in input, and no new objects are created. A kernel that does not ensure exact constructions will be faster, so we use that during construction of the graph.

Now, when you wish to draw the dual, you are creating new geometric entities: the Voronoi vertices. Of course you could use a kernel not providing exact constructions; almost always it will be good enough, but you will have no guarantees that it will, and sometimes it won't [*]. So instead you can use an kernel providing exact constructions, it's slower but it ensures that the geometric positions of the dual vertices are correct. Note that you need a kernel providing exact square roots like EPECK_with_sqrt, and not just EPECK as the latter does not provide exact square roots.

[*] Note that it is the same for the building of the SDG_2 itself: you could use a kernel that does not even provide exact predicates, and it might work just fine most of the time, but it's all about making sure things always work in all configurations.

Also you seem to still discretize the parabolic segments.

Yes, this is just some code that I had lying around where I wanted the result to be segment polylines, hence I discretize the parabolas (but with an adaptive choice of discretization). Nevertheless, I thought it would be useful for you (and others) as you can just make your own example where instead of discretizing the parabola, you do whatever you want with the CGAL::Parabola_segment_2 that is returned from the edge dual function, like you have done in the code above.

@Yvee1
Copy link

Yvee1 commented Jan 11, 2024

Right, thank you for the explanation. I did not realize that the SDG_2 performs no constructions; though, it makes sense as a Delaunay graph of points does not. It's strange though that I get an assertion violation when constructing a SDG_2 with inexact constructions but not with exact constructions (#7978), because if it would perform no constructions there should be no difference right?

@sloriot
Copy link
Member

sloriot commented Jan 24, 2024

Successfully tested in CGAL-6.0-Ic-156

@sloriot sloriot added the Tested label Jan 24, 2024
@lrineau lrineau self-assigned this Jan 24, 2024
@lrineau lrineau added the rm only: ready for master For the release team only: that indicates that a PR is about to be merged in 'master' label Jan 24, 2024
@lrineau lrineau merged commit c87ec5e into CGAL:master Jan 24, 2024
9 checks passed
@lrineau lrineau removed the rm only: ready for master For the release team only: that indicates that a PR is about to be merged in 'master' label Jan 24, 2024
@lrineau lrineau deleted the Parabola_segment_2-GF branch January 24, 2024 15:20
@afabri
Copy link
Member Author

afabri commented May 16, 2024

@MaelRL can one use the kerrnel without sqrt for the construction and the kernel with sqrt only where it is needed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants