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;
}
Related
I am currently trying to implement a motion-planning algorithm and have been using Boost's RTree to do so. Up until now, the RTree has stored std::pair<boost::geometry::model::point<double, 2, bg::cs::cartesian>, unsigned int> and has worked just fine in answering nearest neighbor queries.
Externally, I make use of a custom struct called Node, each of which corresponds to a point in the RTree. I maintain a vector of Nodes so that the ids of the output pairs from the RTree queries can be used as indices to be looked up in the vector.
However, I want to eliminate the use of this large vector to see its results on time and space performance of my algorithm. To do this, I want to replace the use of point in the pairs with Nodes, so that the Nodes are directly output in the query results. To do this I have used boost geometry 2d point registering, with the following code:
#include <algorithm>
#include <iostream>
#include <cmath>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <bits/stdc++.h>
#include <boost/geometry.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <chrono>
using namespace std;
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
struct Node
{
Node *parent;
point pos;
};
typedef pair<Node, unsigned int> ptval;
typedef pair<box, unsigned int> boxval;
BOOST_GEOMETRY_REGISTER_POINT_2D(Node, double, bg::cs::cartesian, pos.get<0>(), pos.get<1>());
int main() {
cout << "hi" << endl; return 0;
}
However, a strange error results:
In file included from rrt.cpp:13:
rrt.cpp: In static member function 'static void boost::geometry::traits::access<Node, 0>::set(Node&, const double&)':
rrt.cpp:45:1: error: assignment of read-only location 'p.Node::pos.boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>::get<0>()'
BOOST_GEOMETRY_REGISTER_POINT_2D(Node, double, bg::cs::cartesian, pos.get<0>(), pos.get<1>());
This is odd as there are no const declarations anywhere here. I'm guessing it has to do with something inside of the hood of the get<>() functions, but I'm not sure exactly what it is.
Any help is appreciated, as I've not found this issue anywhere online.
What version of boost is that? BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET takes 7 parameters, not 5, and it has done so ever since the source file appeared in January 2010, which means Boost 1.47.0.
Looking at the docs, it looks like the () are not supposed to be included on the member functions anyways.
Finally, you have bg::get<0> in your question code, but since that doesn't even match with the error message you show, I'm assuming that's a simple mistake in the question.
Here's a little test program with the fixes I think you wanted:
Live On Coliru
#include <algorithm>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <chrono>
#include <iostream>
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
struct Node {
Node* parent;
point pos;
};
using ptval = std::pair<Node, unsigned int>;
using boxval = std::pair<box, unsigned int>;
BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET( //
Node, double, bg::cs::cartesian, //
pos.get<0>, pos.get<1>, pos.set<0>, pos.set<1>)
int main() {
{
bgi::rtree<ptval, bgi::rstar<16>> index;
Node n{nullptr, {}};
bg::assign_values(n.pos, 10.0, 10.0);
int idx = 0;
index.insert({n, idx++});
for (auto pt : { point{20.0, 10.0}, {20.0, 20.0}, {10.0, 20.0} }) {
bg::assign(n.pos, pt);
index.insert({n, idx++});
}
for (auto& [g, id] : index) {
std::cout << id << ": " << bg::wkt(g) << '\n';
}
}
{
bgi::rtree<boxval, bgi::rstar<16>> index;
index.insert(boxval{{{1, 2}, {3, 4}}, 12});
for (auto& [g, id] : index) {
std::cout << id << ": " << bg::wkt(g) << '\n';
}
}
}
Printing
0: POINT(10 10)
1: POINT(20 10)
2: POINT(20 20)
3: POINT(10 20)
12: POLYGON((1 2,1 4,3 4,3 2,1 2))
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'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();
i am trying to use boost geometry and having trouble assigning points to a polygon.
Lets assume i create an static vector of points
boost::geometry::model::d2::point_xy<double> >* a;
And then i create a polygon:
boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;
Assuming i have already defined the values of the points of a.
How can i assign the points from a to P?
The boost::geometry::assign_points() algorithm can be used to assign a range of points to a polygon.
If a is a range of points and P is a polygon, then one would use:
boost::geometry::assign_points(P, a);
Here is a complete example demonstrating the usage of assign_points:
#include <iostream>
#include <vector>
#include <boost/assign/std/vector.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/dsv/write.hpp>
int main()
{
using namespace boost::assign;
typedef boost::geometry::model::d2::point_xy<double> point_xy;
// Create points to represent a 5x5 closed polygon.
std::vector<point_xy> points;
points +=
point_xy(0,0),
point_xy(0,5),
point_xy(5,5),
point_xy(5,0),
point_xy(0,0)
;
// Create a polygon object and assign the points to it.
boost::geometry::model::polygon<point_xy> polygon;
boost::geometry::assign_points(polygon, points);
std::cout << "Polygon " << boost::geometry::dsv(polygon) <<
" has an area of " << boost::geometry::area(polygon) << std::endl;
}
Which produces the following output:
Polygon (((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))) has an area of 25
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.