I'm currently learning to perform 3D triangulation using CGAL, and so far I've managed to create a regular tetrahedron by inserting and triangulating 4 vertices. But when I try to loop over the edges of the tetrahedron and obtain the vertices corresponding to that edge, I get the origin as a vertex or duplicates of previous edges. In 2D it all works fine, but in 3D things go wrong. I think this is related to an infinite/undefined vertex being included, but I don't know how to deal with this. Any help would be appreciated.
My code (modified from this question):
#include <vector>
#include <iostream>
#include <cmath>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_3<K> Delaunay;
typedef K::Point_3 Point;
void load_points(std::vector<Point>& rPoints)
{
rPoints.push_back(Point(1.0, 0.0, -1.0/sqrt(2))); // first point
rPoints.push_back(Point(-1.0, 0.0, -1.0/sqrt(2))); // second point
rPoints.push_back(Point(0.0, 1.0, 1.0/sqrt(2))); // third point
rPoints.push_back(Point(0.0, -1.0, 1.0/sqrt(2))); // fourth point
}
int main()
{
std::vector<Point> points;
load_points(points);
Delaunay dt;
dt.insert(points.begin(),points.end());
for(Delaunay::Finite_edges_iterator it = dt.finite_edges_begin(); it != dt.finite_edges_end(); ++it)
{
Point i1= it->first->vertex( (it->second+1)%3 )->point();
Point i2= it->first->vertex( (it->second+2)%3 )->point();
std::cout << "i1: " << i1 << "\t i2: " << i2 << "\n";
}
return 0;
}
The documentation for an edge indicates that it's a triple: (c,i,j) is the edge of cell c whose vertices indices are i and j.
So in your code you should write:
Point i1= it->first->vertex( it->second )->point();
Point i2= it->first->vertex( it->third )->point();
Related
I'm new and I have a std::vector of cv::Point2i:
vector<Point2i> x_y;
And I want to sort them clockwise!
How can I do it?
You can use std::sort.
Overload (3) accepts a custom comparator, that should:
returns ​true if the first argument is less than (i.e. is ordered
before) the second.
Your comparator should compare the angles of the lines connecting the points to the origin (or to any other rotation pivot).
Here is a complete example (replace Point with cv::Point2i):
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath>
struct Point
{
int x;
int y;
};
int main()
{
std::vector<Point> points = { {0,1}, {-1,0}, {-1,1}, {1,0} };
Point pivot{ 0,0 }; // Select a point from the vector, or any other (will be used as rotation center).
std::sort(points.begin(),
points.end(),
[pivot](Point const& p1, Point const& p2)
{ return std::atan2(p1.y - pivot.y, p1.x - pivot.x) > std::atan2(p2.y - pivot.y, p2.x - pivot.x); });
for (auto const& p : points)
{
std::cout << "{" << p.x << "," << p.y << "}" << std::endl;
}
}
Note that I used > in the comparator to get a clockwise order (in which large angles should come before small ones). Use < for an anti-clockwise order).
Output:
{-1,0}
{-1,1}
{0,1}
{1,0}
I want to efficiently create a list of the vertex number of a polygon that intersects. This in order to check if I move the polygons slightly I can check whether it is the same intersection or a completely different one. Presumably if at least one vertex number remains in the list it is the same intersection.
So I have polygon P and Q at t=0 intersecting, this should give me vertex number [1,2,3] for P and [2] for polygon Q, see image for clarification. At t=1 I would get [1,2] for P and [2] for Q.
Currently I first retrieve the intersection and than for both polygons loop through the vertices and use the has_on_boundary function to determine if it is part of the intersection and store the vertex number. See code:
//Standard Includes
#include <iostream>
using std::cout;
using std::endl;
//Include CGAL options
#define CGAL_HEADER_ONLY 1 //Defining to use the CGAL library as header only
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
//Typedefs for CGAL Uses.
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
typedef std::vector<Polygon_with_holes_2> Pwh_list_2;
int main() {
Polygon_2 P;
P.push_back(Point_2(-1, 1));
P.push_back(Point_2(-0.01, -1));
P.push_back(Point_2(0, -1));
P.push_back(Point_2(0.01, -1));
P.push_back(Point_2(1, 1));
Polygon_2 Q;
Q.push_back(Point_2(-1, -1));
Q.push_back(Point_2(1, -1));
Q.push_back(Point_2(0, 1));
Pwh_list_2 polygon_intersections;
CGAL::intersection(P, Q, std::back_inserter(polygon_intersections));
//For ease now only assume one intersection
Polygon_2 intersection = polygon_intersections[0].outer_boundary();
//Get vertex number of P in intersection
int vertex_nr = 0;
std::set<int> overlapping_vertices_P;
cout << "Find intersection vertices of Polygon P" << endl;
for (auto it = P.vertices_begin(); it != P.vertices_end(); ++it, ++vertex_nr) {
if (intersection.has_on_boundary(*it)) {
overlapping_vertices_P.insert(vertex_nr);
cout << vertex_nr << endl;
}
}
//Get vertex number of Q in intersection
vertex_nr = 0;
std::set<int> overlapping_vertices_Q;
cout << "Find intersection vertices of Polygon Q" << endl;
for (auto it = Q.vertices_begin(); it != Q.vertices_end(); ++it, ++vertex_nr) {
if (intersection.has_on_boundary(*it)) {
overlapping_vertices_Q.insert(vertex_nr);
cout << vertex_nr << endl;
}
}
return 0;
}
Question: It works but seems very inefficient to me. Is there a better way to do this?
Any help or suggestions are highly appreciated.
I am trying to use Boost to embed a planar graph using the Chrobak-Payne algorithm.
I am able to run the example successfully, but when I try to modify it and use different graphs it does not work correctly. I am trying to embed the second platonic graph but it does not work, and my code crashes with "Segmentation fault: 11". I assumed it is because I needed to use make_connected, make_biconnected_planar, and make_maximal_planar, but adding them did not fix it.
Here is the modified source example using the second platonic graph and the three helper functions:
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#include <vector>
#include <boost/graph/planar_canonical_ordering.hpp>
#include <boost/graph/is_straight_line_drawing.hpp>
#include <boost/graph/chrobak_payne_drawing.hpp>
#include <boost/graph/boyer_myrvold_planar_test.hpp>
using namespace boost;
//a class to hold the coordinates of the straight line embedding
struct coord_t
{
std::size_t x;
std::size_t y;
};
int main(int argc, char** argv)
{
typedef adjacency_list
< vecS,
vecS,
undirectedS,
property<vertex_index_t, int>,
property<edge_index_t, int>
>
graph;
graph g(7);
add_edge(0,1,g);
add_edge(1,2,g);
add_edge(2,3,g);
add_edge(3,0,g);
add_edge(0,4,g);
add_edge(1,5,g);
add_edge(2,6,g);
add_edge(3,7,g);
add_edge(4,5,g);
add_edge(5,6,g);
add_edge(6,7,g);
add_edge(7,4,g);
make_connected(g); //Make connected (1/3)
//Compute the planar embedding as a side-effect
typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
std::vector<vec_t> embedding(num_vertices(g));
boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
boyer_myrvold_params::embedding =
&embedding[0]
);
make_biconnected_planar(g, &embedding[0]); //Make biconnected planar (2/3)
make_maximal_planar(g, &embedding[0]); //Make maximal planar (3/3)
//Find a canonical ordering
std::vector<graph_traits<graph>::vertex_descriptor> ordering;
planar_canonical_ordering(g, &embedding[0], std::back_inserter(ordering));
//Set up a property map to hold the mapping from vertices to coord_t's
typedef std::vector< coord_t > straight_line_drawing_storage_t;
typedef boost::iterator_property_map
< straight_line_drawing_storage_t::iterator,
property_map<graph, vertex_index_t>::type
>
straight_line_drawing_t;
straight_line_drawing_storage_t straight_line_drawing_storage
(num_vertices(g));
straight_line_drawing_t straight_line_drawing
(straight_line_drawing_storage.begin(),
get(vertex_index,g)
);
// Compute the straight line drawing
chrobak_payne_straight_line_drawing(g,
embedding,
ordering.begin(),
ordering.end(),
straight_line_drawing
);
std::cout << "The straight line drawing is: " << std::endl;
graph_traits<graph>::vertex_iterator vi, vi_end;
for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
coord_t coord(get(straight_line_drawing,*vi));
std::cout << *vi << " -> (" << coord.x << ", " << coord.y << ")"
<< std::endl;
}
// Verify that the drawing is actually a plane drawing
if (is_straight_line_drawing(g, straight_line_drawing))
std::cout << "Is a plane drawing." << std::endl;
else
std::cout << "Is not a plane drawing." << std::endl;
return 0;
}
But for some reason I am still getting a segmentation fault. I know it is at the call:
chrobak_payne_straight_line_drawing(g,
embedding,
ordering.begin(),
ordering.end(),
straight_line_drawing
);
because it runs fine without it (but does not compute the embedding). Where is the memory issue causing this segmentation fault? The graph I am embedding is smaller than the example.
From must be a maximal planar graph with at least 3 vertices, the requirement that k > 2 is needed for success. Your call to Planar Canonical Ordering returned two vertices. Catch is chrobak_payne_straight_line_drawing does no checking for you and it asserts at the vector iterator test in the std.
add:
assert( ordering.size( ) > 2 );
before calling, or a conditional, depends what you are up to.
one more edge:
add_edge(1,4,g);
And it would have worked.
Given the vertices of two convex polygons, what is the simplest way of computing the area of their intersection using cgal?
Because you are working with convex polygons, there is no need to worry about holes. So the simplest code that I can think of is basically construct the polygons, call intersection, loop over intersection and total up the area::
#include <iostream>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/Polygon_with_holes_2.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Polygon_2_algorithms.h>
typedef CGAL::Simple_cartesian<double> K;
typedef K::Point_2 Point;
typedef CGAL::Polygon_2<K> Polygon_2;
typedef CGAL::Polygon_with_holes_2<K> Polygon_with_holes_2;
using std::cout; using std::endl;
int main(){
Point points[] = { Point(0,0), Point(1,0), Point(1,1), Point(0,1)};
Point points2[] = { Point(0.5,0.5), Point(1.5,0.5), Point(1.5,1.5), Point(0.5,1.5)};
Polygon_2 poly1(points, points+4);
Polygon_2 poly2(points2, points2+4);
//CGAL::General_polygon_with_holes_2<K> poly3;
std::list<Polygon_with_holes_2> polyI;
CGAL::intersection(poly1, poly2, std::back_inserter(polyI));
double totalArea = 0;
typedef std::list<Polygon_with_holes_2>::iterator LIT;
for(LIT lit = polyI.begin(); lit!=polyI.end(); lit++){
totalArea+=lit->outer_boundary().area();
}
cout << "TotalArea::" << totalArea;
}
After reading about it I've come to this:
#include <vector>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_2<K> Delaunay;
typedef K::Point_2 Point;
void load_points(std::vector< Point >& points)
{
points.push_back(Point(1., 1.));
points.push_back(Point(2., 1.));
points.push_back(Point(2., 2.));
points.push_back(Point(1., 2.));
}
int main()
{
std::vector< Point > points;
load_points(points);
Delaunay dt;
dt.insert(points.begin(), points.end());
std::cout << dt.number_of_vertices() << std::endl;
typedef std::vector<Delaunay::Face_handle> Faces;
Faces faces;
std::back_insert_iterator<Faces> result( faces );
result = dt.get_conflicts ( Delaunay::Point(1.5, 1.5),
std::back_inserter(faces) );
return 0;
}
That should find the faces whose circumcircle contains the point. After that, I'd have to take these triangles and use a method to test if the point is inside them I think (does CGAL do this? I know it's easy to implement though).
Anyway, how can I get the triangles out of faces?
Answer is
CGAL::Triangle_2<K> f = dt.triangle(faces[0]);
std::cout << dt.triangle(faces[0]) << std::endl;
std::cout << dt.triangle(faces[1]) << std::endl;
etc
I don't know how to use the Triangle class well but it's a start at least.
I was gonna make an actual answer but stackoverflow didn't allow me to so.
You should use the locate member function which documentation can be found here.