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
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 have array of point with latitude and longitude, from this array generating LineString to display way on road by leaflet.
Now i want to improve code function to detect when user point (received from GPS device):
1) Out from waypoint
2) Position on waypoint
3) Direction (begin or back)
After having tried many ways to implement my idea i coming to convert my array of point to Polygon and control by boost::geometry::intersection
I tried realise this function by search near point in array that work perfect in one way road else code can lock point from neighbour way :(
Example of ways:
[start]--------------[end]
But it can be so
[start]
---------one_road---turning_road_and_reverse-]
-------two_road-----------
[end]
Now i want to convert array to one polygon
-----------------------------------------------
one_road
two_road
-----------------------------------------------
i think that i can easily release function to detect location without errors
May be someone know how easily convert linestring to polygon?
example
i have:
LINESTRING(-105.40392744645942 38.49004450086558,-105.40486621961463 38.491262147649266,-105.40443706617225 38.49272329662804,-105.40424394712318 38.49368058506501,-105.4055099497782 38.49443633010962,-105.40690469846595 38.494940155735165,-105.40694761381019 38.49450350706328,-105.40634679899085 38.49324392875914,-105.40510225400794 38.49146368720108,-105.40437269315589 38.490422393448746,-105.40394675757852 38.489957795386)
i want:
POLYGON((-105.40419674129225 38.49056599190572,-105.40475464076735 38.49046522094479,-105.40737247676589 38.494462360981586,-105.40685749263503 38.49520130375959,-105.40647554502357 38.493848529093356,-105.4052739153849 38.49193394396309,-105.4047160159098 38.49237060820819,-105.40473747358192 38.49344546276763,-105.40600347623695 38.49430197601443,-105.40664720640052 38.49480580257953,-105.40585327253211 38.494789008417456,-105.40432977781165 38.49394929532246,-105.40394353971351 38.493059188756156,-105.40465164289344 38.49129573761371,-105.40419674129225 38.49056599190572))
Please help!
Your question is in serious need of a SSCCE. Reading it you might be looking for anything from trivial type conversion to complicated routing algorithms.
Here's are two simple SSCCE's that show how to do the type conversions you describe.
NOTE The extra work to check that the polygon is valid (it needs to be closed, and the points need to have the correct orientation for the outer ring)
Array Of Point To Polygon
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <iostream>
#include <boost/geometry/io/io.hpp>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using point = bgm::d2::point_xy<int>;
using polygon = bgm::polygon<point>;
void debug_print(polygon const& p) {
std::string reason;
bool valid = bg::is_valid(p, reason);
std::cout << bg::dsv(p) << " - " << (!valid?"invalid ("+reason+")":"valid") << "\n";
}
int main() {
point arr[] { {1,3}, {4,5}, {9, 0} };
for (auto& p : arr)
std::cout << bg::wkt(p) << " ";
std::cout << "\n";
polygon p { {std::begin(arr), std::end(arr)} };
debug_print(p);
bg::correct(p);
debug_print(p);
std::cout << bg::wkt(p) << "\n";
}
Prints:
POINT(1 3) POINT(4 5) POINT(9 0)
(((1, 3), (4, 5), (9, 0))) - invalid (Geometry has too few points)
(((1, 3), (4, 5), (9, 0), (1, 3))) - valid
POLYGON((1 3,4 5,9 0,1 3))
LineString To Polygon
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <iostream>
#include <boost/geometry/io/io.hpp>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using point = bgm::d2::point_xy<int>;
using linestring = bgm::linestring<point>;
using ring = bgm::ring<point>;
using polygon = bgm::polygon<point>;
void debug_print(polygon const& p) {
std::string reason;
bool valid = bg::is_valid(p, reason);
std::cout << bg::dsv(p) << " - " << (!valid?"invalid ("+reason+")":"valid") << "\n";
}
int main() {
linestring ls { {1,3}, {4,5}, {9, 0} };
std::cout << bg::wkt(ls) << "\n";
polygon p { ring{ls.begin(), ls.end()} };
debug_print(p);
bg::correct(p);
debug_print(p);
std::cout << bg::wkt(p) << "\n";
}
Prints
LINESTRING(1 3,4 5,9 0)
(((1, 3), (4, 5), (9, 0))) - invalid (Geometry has too few points)
(((1, 3), (4, 5), (9, 0), (1, 3))) - valid
POLYGON((1 3,4 5,9 0,1 3))
i found solution this is boost::geometry::buffer
using namespace boost::geometry::model;
namespace bg = boost::geometry;
typedef bg::model::point <double , 2, bg::cs::cartesian > point_t;
typedef boost::geometry::model::polygon <point_t> polygon_t;
typedef bg::model::linestring<point_t> linestring_t;
linestring_t ls1;
vector<BSONElement> point_records = record.getField("points").Array();
linestring_t ls1;
for(vector<BSONElement>::iterator it = point_records.begin(); it != point_records.end(); ++it)
{
BSONObj point_record = (*it).Obj();
bg::append(ls1, point_t(point_record.getField("lo").Double(), point_record.getField("lat").Double()));
}
const double buffer_distance = 1.0;
const int points_per_circle = 36;
// Declare other strategies
boost::geometry::strategy::buffer::distance_symmetric<double> distance_strategy(0.0002);
boost::geometry::strategy::buffer::join_round join_strategy(points_per_circle);
boost::geometry::strategy::buffer::end_round end_strategy(points_per_circle);
boost::geometry::strategy::buffer::point_circle circle_strategy(points_per_circle);
boost::geometry::strategy::buffer::side_straight side_strategy;
boost::geometry::model::multi_polygon<polygon_t> result;
/* polygon_t result; */
boost::geometry::buffer(ls1, result,
distance_strategy, side_strategy,
join_strategy, end_strategy, circle_strategy);
Please sorry for bad english!
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();
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;
}