I am trying to use the boost geometry method intersects with my own point class, successfully registered with the boost geometry library.
The boost documentation ( https://www.boost.org/doc/libs/1_73_0/libs/geometry/doc/html/geometry/reference/algorithms/intersection/intersection_3.html ) says that I can use a vector of points as the output parameter. So I wrote this:
#include <iostream>
#include <deque>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
namespace bg = boost::geometry;
using namespace std;
class cxy
{
public:
double x;
double y;
cxy( double X, double Y )
: x( X )
, y( Y )
{
}
/// boost geometry insists on a default constructor
cxy()
: cxy(0,0)
{
}
};
BOOST_GEOMETRY_REGISTER_POINT_2D( cxy, double, bg::cs::cartesian, x, y )
typedef bg::model::segment<cxy> segment_t;
int main()
{
cxy a(0,0);
cxy b(1,1);
cxy c(1,0);
cxy d(0,1) ;
std::vector<cxy> out;
//////////////// this compiles
bg::intersection(segment_t{a, b}, segment_t{c, d}, out);
//////////////// this does not!!!
segment_t ab( a, b );
segment_t cd( c, d );
bg::intersects( ab, cd, out );
return 0;
}
To be clear: my problem was that I was confused between intersection and intersects
The following code compiles and produces the expected results:
#include <iostream>
#include <deque>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
namespace bg = boost::geometry;
using namespace std;
class cxy
{
public:
double x;
double y;
cxy( double X, double Y )
: x( X )
, y( Y )
{
}
/// boost geometry insists on a default constructor
cxy()
: cxy(0,0)
{
}
};
BOOST_GEOMETRY_REGISTER_POINT_2D( cxy, double, bg::cs::cartesian, x, y )
typedef bg::model::segment<cxy> segment_t;
int main()
{
cxy a(0,0);
cxy b(1,1);
cxy c(1,0);
cxy d(0,1) ;
segment_t ab( a, b );
segment_t cd( c, d );
std::vector<cxy> out;
if( ! bg::intersection( ab, cd, out ) ) {
std::cout << "no intersection\n";
return 1;
}
std::cout << "intersection at " << out[0].x <<" " << out[0].y << "\n";
return 0;
}
You're asking "whether a intersects b".
However, your third argument suggests you wanted instead to ask for "the intersection":
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <iostream>
namespace bg = boost::geometry;
using namespace std;
struct cxy {
double x = 0;
double y = 0;
cxy(double X, double Y) : x(X), y(Y) {}
cxy() = default;
};
BOOST_GEOMETRY_REGISTER_POINT_2D(cxy, double, bg::cs::cartesian, x, y)
using segment_t = bg::model::segment<cxy>;
using points_t = bg::model::multi_point<cxy>;
int main() {
cxy a{0, 0}, b{1, 1}, c{1, 0}, d{0, 1};
std::vector<cxy> out;
bg::intersection(segment_t{a, b}, segment_t{c, d}, out);
// for output, use a multipoint model or register your vector as one
points_t pts;
bg::intersection(segment_t{a, b}, segment_t{c, d}, pts);
std::cout << bg::wkt(pts) << "\n";
}
Prints
MULTIPOINT((0.5 0.5))
Related
I need to solve the optimization problem: . A and b are known. I use Zero to represent A and b to facilate the expression in the following code. The error is caused by problem.AddResidualBlock(cost_function, nullptr, &X); because the third argument needs to be double type and X is a vector with 50 elements. Can you give me some advice?
#include <cmath>
#include <ceres/ceres.h>
#include <Eigen/Core>
#include <Eigen/Eigen>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/StdVector>
#define PhaseNums 25
using namespace std;
using namespace ceres;
using namespace Eigen;
struct GammaResidual
{
GammaResidual(const MatrixXf A, const VectorXf b) : A_(A), b_(b) {}
template <typename T>
bool operator()(const T* const x, T* residual) const {
residual[0] = (A_ * x[0] - b_).transpose() * (A_ * x[0] - b_);
return true;
}
private:
const MatrixXf A_;
const VectorXf b_;
};
int main()
{
MatrixXf A = MatrixXf::Zero(2 * PhaseNums, 2 * PhaseNums);
VectorXf b = VectorXf::Zero(2 * PhaseNums);
VectorXf X = VectorXf::Zero(2 * PhaseNums);
Problem problem;
CostFunction* cost_function = new AutoDiffCostFunction<GammaResidual, 1, 1>(
new GammaResidual(A, b));
problem.AddResidualBlock(cost_function, nullptr, &X);
ceres::Solver::Options options;
options.minimizer_progress_to_stdout = true;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
cout << summary.BriefReport() << endl;
}
I guess that If your X is a vector, you need to loop through it and add a residual a residual block for each x. Makes sense?
I need to write constructors for my 3x3 matrix class. I'm not sure whether I'm doing it efficiently and I do not know how to use initializer_list.. I would like a constructor that creates by default the identity matrix, and receives parameteres to set a diagonal matrix. Then I'd also like a constructor that takes a list of cofficients (with initialization_list) and puts them in the matrix. This is what I have:
#include <iostream>
#include <array>
#include <cmath>
#include <initializer_list>
#include "Vecteur.h"
using namespace std;
class Matrice33 {
private :
array<array<double,3>,3> matrice;
public :
Matrice33(double a = 1, double b=1, double c=1)
{ matrice[0][0] = a; matrice[1][1]= b; matrice [2][2]= c;
matrice[0][1] = 0; matrice[0][2] = 0;
matrice[1][0] = 0; matrice[1][2] = 0;
matrice[2][0] = 0; matrice[2][1] = 0;} \\ IS THIS THE ONLY WAY TO SET THE MATRIX OR IS
\\THERE A QUICKER ONE?
Matrice33(initilizer_liste<double> cosnt& coeff)
{ for( auto c : coeff) \\ I DON'T KNOW HOW TO WRITE THIS CONSTRUCTOR...
void affiche() const { for(auto m : matrice){
for(auto n : m) {
cout<<n<<" ";}
cout<<endl;}}
};
int main(){
Matrice33 mat(1.1, 1.2, 1.3,
2.1, 2.2, 2.3,
3.1, 3.2, 3.3); \\I'D LIKE THIS TO BE TAKEN AS THE LIST BY MY CONSTRUCTOR, FOR
\\EXAMPLE
Matrice33 m(2.0,3.0,1.0);
m.affiche(); \\ WHEN I EXECUTE I DON'T GET ANY OUTPUT..
return 0;
}
This is changed version of your code that is just working.
#include <iostream>
#include <array>
#include <cmath>
#include <initializer_list>
#include <vector>
using namespace std;
class Matrice33
{
public:
Matrice33(double a = 1, double b = 1, double c = 1)
: matrice{{ {{a, 0, 0}}, {{0, b, 0}}, {{0, 0, c}} }}
{
}
Matrice33(const std::initializer_list<std::initializer_list<double>> & coeff)
{
int counter = 0;
for (auto row : coeff)
{
copy(row.begin(), row.end(), matrice[counter++].begin());
}
}
void affiche()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << matrice[i][j] << " ";
}
cout << endl;;
}
}
private:
array<array<double, 3>, 3> matrice;
};
int main()
{
Matrice33 mat{ {1.1, 1.2, 1.3},{2.1, 2.2, 2.3},{3.1, 3.2, 3.3} };
mat.affiche();
Matrice33 m(2.0, 3.0, 1.0);
m.affiche();
return 0;
}
You can use perfect forwarding and template constructor here.
template<typename... Args>
Matrice33(Args&&... args) : matrice(std::forward<Args>(args)...) {}
then initialization will be same as intitialization of std::array.
I am trying to calculate distance between a point and a line segment. But the following code terminates during runtime abruptly (#comparable_distance).
using namespace std;
namespace bg = boost::geometry;
class Vertex {
public:
Vertex(int px, int py):x(px), y(py){}
int x;
int y;
};
BOOST_GEOMETRY_REGISTER_POINT_2D(Vertex, double, cs::cartesian, x, y)
typedef Vertex* vertref;
typedef bg::model::segment<vertref> segment_type;
std::vector<segment_type> segments;
int main()
{
segment_type l(new Vertex(1,2), new Vertex(2,2));
Vertex p(4,5);
double comp_dist = 0;
comp_dist = bg::comparable_distance(p, l);
cout<<comp_dist<<endl;
return 0;
}
If I replace bg::model::segment with linestring; add two points to it, it works without any error as in below ...
using namespace std;
namespace bg = boost::geometry;
class Vertex {
public:
Vertex(int px, int py):x(px), y(py){}
int x;
int y;
};
BOOST_GEOMETRY_REGISTER_POINT_2D(Vertex, double, cs::cartesian, x, y)
typedef Vertex* vertref;
typedef bg::model::linestring<vertref> segment_type;
std::vector<segment_type> segments;
int main()
{
segment_type l;
l.push_back(new Vertex(1,2));
l.push_back(new Vertex(2,2));
Vertex p(4,5);
double comp_dist = 0;
comp_dist = bg::comparable_distance(p, l);
cout<<comp_dist<<endl;
return 0;
}
Any ideas what I am doing wrong in the first code using segment?
Thanks!
Call Stack ...
#0 0x40486f boost::geometry::traits::access<Vertex, 0u, void>::set(p=..., value=#0x63fde8: 1) (C:\Projects\test\main.cpp:17)
#1 0x403e14 boost::geometry::core_dispatch::access<boost::geometry::point_tag, Vertex, double, 0u, boost::integral_constant<bool, true> >::set(p=0x77b12580, value=#0x63fde8: 1) (C:/boost_1_68_0/boost/geometry/core/access.hpp:187)
#2 0x404182 boost::geometry::set<0u, Vertex*>(geometry=#0x63fe34: 0x77b12580, value=#0x63fde8: 1, dummy=0x0) (C:/boost_1_68_0/boost/geometry/core/access.hpp:321)
#3 0x40469a boost::geometry::detail::assign::assign_point_from_index<boost::geometry::model::segment<Vertex*>, Vertex*, 0u, 0u, 2u>::apply(geometry=..., point=#0x63fe34: 0x77b12580) (C:/boost_1_68_0/boost/geometry/algorithms/detail/assign_values.hpp:195)
#4 0x4045de boost::geometry::detail::assign_point_from_index<0u, Vertex*, boost::geometry::model::segment<Vertex*> >(geometry=..., point=#0x63fe34: 0x77b12580) (C:/boost_1_68_0/boost/geometry/algorithms/detail/assign_indexed_point.hpp:80)
#5 0x4049fc boost::geometry::dispatch::distance<Vertex, boost::geometry::model::segment<Vertex*>, boost::geometry::strategy::distance::projected_point<void, boost::geometry::strategy::distance::comparable::pythagoras<void> >, boost::geometry::point_tag, boost::geometry::segment_tag, boost::geometry::strategy_tag_distance_point_segment, false>::apply(point=..., segment=..., strategy=...) (C:/boost_1_68_0/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp:419)
#6 0x403f9b boost::geometry::resolve_strategy::comparable_distance::apply<Vertex, boost::geometry::model::segment<Vertex*> >(geometry1=..., geometry2=...) (C:/boost_1_68_0/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:83)
#7 0x403f38 boost::geometry::resolve_variant::comparable_distance<Vertex, boost::geometry::model::segment<Vertex*> >::apply<boost::geometry::default_strategy>(geometry1=..., geometry2=..., strategy=...) (C:/boost_1_68_0/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:106)
#8 0x403ff5 boost::geometry::comparable_distance<Vertex, boost::geometry::model::segment<Vertex*>, boost::geometry::default_strategy>(geometry1=..., geometry2=..., strategy=...) (C:/boost_1_68_0/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:328)
#9 0x403fc9 boost::geometry::comparable_distance<Vertex, boost::geometry::model::segment<Vertex*> >(geometry1=..., geometry2=...) (C:/boost_1_68_0/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:356)
#10 0x401518 main() (C:\Projects\test\main.cpp:30)
The Segment Concept is modeled by model::segment, which takes a template parameter that models a Point.
Now you used:
typedef Vertex *vertref;
typedef bg::model::segment<vertref> segment_type;
Note that vertref does not in fact model the Point concept. So, by contrast, consider:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <iostream>
namespace bg = boost::geometry;
struct Vertex {
double x;
double y;
};
BOOST_GEOMETRY_REGISTER_POINT_2D(Vertex, double, bg::cs::cartesian, x, y)
typedef bg::model::segment<Vertex> segment_type;
int main() {
segment_type l({1, 2}, {2, 2});
Vertex p {4, 5};
auto comp_dist = bg::comparable_distance(p, l);
std::cout << comp_dist << "\n";
}
Prints:
13
Indeed 13 is the square of the actual distance:
BONUS
In response to the comment, yes there's even an out-of-the-box model for segments referring to points (from other geometries). Here's how to use referring_segment<>:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <iostream>
namespace bg = boost::geometry;
struct Vertex {
double x;
double y;
};
BOOST_GEOMETRY_REGISTER_POINT_2D(Vertex, double, bg::cs::cartesian, x, y)
typedef bg::model::referring_segment<Vertex> segment_type;
int main() {
Vertex A{1,2},
B{2,2};
segment_type l(A, B);
Vertex p {4, 5};
std::cout << bg::distance(p, l) << "\n";
bg::multiply_value(A, -1);
bg::multiply_value(B, -1);
std::cout << bg::distance(p, l) << "\n";
}
Which prints distance before and after mutation:
3.60555
8.60233
Again this matches what you'd expect to see:
Notes:
using new in C++ is almost always a mistake. This mistake is most often made by beginners coming from garbage-collected languages like Java or C# (Why should C++ programmers minimize use of 'new'?)
there was an inconsistency of types (the members x, y were ints)
I have some double variables: a, b,c...
I want to construct a vector v such as v[0]=a, v[1]=b etc
Can I do this with C++11 list initializer ? i.e this syntax :
std::vector<double> v{a,b,c};
If no, is there a way to do this directly, without multiple pushback() ?
You can answer questions like this easily using this online C++ compiler: http://webcompiler.cloudapp.net/
I tried this and it worked:
#include <vector>
int main()
{
double a{}, b{}, c{};
std::vector<double> v{a,b,c};
}
A parody on the post of #Chris Guzak:)
I tried this and it worked:
#include <iostream>
#include <functional>
#include <vector>
int main()
{
double a = 1.1, b = 2.2, c = 3.3;
std::vector<double> v { std::cref( a ), std::cref( b ), std::cref( c ) };
for ( double x : v ) std::cout << x << ' ';
std::cout << std::endl;
}
One more parody.
Wow! I tried this and it worked:
#include <iostream>
#include <vector>
int main()
{
double a = 1.1, b = 2.2, c = 3.3;
std::vector<double> v;
v.reserve( 3 );
for ( auto x : { a, b, c } ) v.push_back( x );
for ( double x : v ) std::cout << x << ' ';
std::cout << std::endl;
}
And one more
I tried this and it worked:
#include <iostream>
#include <vector>
int main()
{
double a = 1.1, b = 2.2, c = 3.3;
std::vector<double> v;
v.insert( v.end(), { a, b, c } );
for ( double x : v ) std::cout << x << ' ';
std::cout << std::endl;
}
Oh, and I tried this and it also worked:
#include <iostream>
#include <vector>
int main()
{
double a = 1.1, b = 2.2, c = 3.3;
std::vector<double> v;
v.assign( { a, b, c } );
for ( double x : v ) std::cout << x << ' ';
std::cout << std::endl;
}
What else I did not try?:)
I'm trying to create an array of functors at compile time, like so: (complete file):
#include <functional>
using namespace std;
function< float( float tElevation, float pAzimuth )> colorFunctions[] = {
[]( float tElevation, float pAzimuth ) -> float {
return 2.0f ;
},
} ;
int main()
{
}
That works fine.
But as soon as you try to create a local inside the functor block, like this:
function< float( float tElevation, float pAzimuth )> colorFunctions[] = {
[]( float tElevation, float pAzimuth ) -> float {
float v = 2.0f ;
return v ;
},
} ;
You get Error 1 error C1506: unrecoverable block scoping error
How can I declare locals inside these blocks? It doesn't seem to work.
I can reproduce this on MSVC 2010, SP1. VS10 is known for some problems with lambdas and scoping. I've tried around a lot but found nothing beautiful. Ugly, ugly workaround that will have some initialization overhead but else work as intended:
#include <functional>
#include <boost/assign/list_of.hpp>
#include <vector>
using namespace std;
typedef function< float( float tElevation, float pAzimuth )> f3Func;
vector<f3Func const> const colorFunctions = boost::assign::list_of(
f3Func([]( float /*tElevation*/, float /*pAzimuth*/ ) -> float {
float v = 2.0f ;
return v ;
}))
([](float a, float b) -> float {
float someFloat = 3.14f;
return a*b*someFloat;
})
;
#include <iostream>
int main()
{
cout << colorFunctions[1](0.3f,0.4f) << '\n';
}
I compiled the following code on ubuntu 12.04 with the following line:
g++-4.7 -std=c++0x main.cpp
And it worked fine.
What platform and what compiler are you using?
#include <iostream>
#include <functional>
using namespace std;
function<float (float,float)> funcs[] = {
[] (float a, float b) -> float {
float c = 2.0f;
return c;
}
};
int main() {
std::cout << funcs[0](1,2) << std::endl;
}