Cutting geometries into pieces using boost - c++

Is there any built-in instrument in boost::geometry to cut geomtries like on the picture below? My idea is to find an intersection geometries, and substract them from both sources. But it feels like not the best solution, when there's more than 2 intersecting rectangles that shares same area.
So, translating the input data to a isomorphic test case in code:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/io/io.hpp>
#include <iostream>
#include <fstream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using point = bgm::d2::point_xy<int>;
using poly = bgm::polygon<point>;
using mpoly = bgm::multi_polygon<poly>;
int main()
{
poly a, b, c;
bg::read_wkt("POLYGON((0 0 0 6 6 6 6 0 0 0))", a);
bg::read_wkt("POLYGON((4 -1 4 4 5 4 5 -1 4 -1))", b);
bg::read_wkt("POLYGON((3 -3 3 3 9 3 9 -3 3 -3))", c);
std::cout << bg::wkt(a) << "\n";
std::cout << bg::wkt(b) << "\n";
std::cout << bg::wkt(c) << "\n";
{
std::ofstream svg("output.svg");
boost::geometry::svg_mapper<point> mapper(svg, 400, 400);
mapper.add(a);
mapper.add(b);
mapper.add(c);
mapper.map(a, "fill-opacity:0.2;fill:rgb(0,0,153);stroke:rgb(0,0,200);stroke-width:2");
mapper.map(b, "fill-opacity:0.2;fill:rgb(153,0,0);stroke:rgb(200,0,0);stroke-width:2");
mapper.map(c, "fill-opacity:0.2;fill:rgb(0,153,0);stroke:rgb(0,200,0);stroke-width:2");
}
}
Which reflects the following SVG:

Consider the following code:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry.hpp>
#include <boost/foreach.hpp>
#include <boost/foreach.hpp>
namespace bg = boost::geometry;
namespace bgm = bg::model;
typedef bgm::d2::point_xy<int> point;
typedef bgm::polygon<point> poly;
typedef bgm::multi_polygon<poly> mpoly;
int main()
{
poly a, b, c;
bg::read_wkt("POLYGON((0 0 0 6 6 6 6 0 0 0))", a);
bg::read_wkt("POLYGON((4 -1 4 4 5 4 5 -1 4 -1))", b);
bg::read_wkt("POLYGON((3 -3 3 3 9 3 9 -3 3 -3))", c);
std::vector<poly> polies;
polies.push_back(a);
polies.push_back(b);
polies.push_back(c);
std::vector<poly> res;
for (size_t i = 0; i < polies.size(); ++i)
{
for (size_t j = i; j < polies.size(); ++j)
{
boost::geometry::model::multi_polygon<poly> output;
boost::geometry::union_(polies[i], polies[j], output);
for (auto it = output.begin(); it != output.end(); ++it)
{
res.push_back(*it);
}
}
}
for (size_t i = 0; i < polies.size(); ++i)
{
for (size_t j = i; j < polies.size(); ++j)
{
boost::geometry::model::multi_polygon<poly> multi;
boost::geometry::sym_difference(polies[i], polies[j], multi);
for (auto it = multi.begin(); it != multi.end(); ++it)
{
res.push_back(*it);
}
}
}
{
std::ofstream svg("output2.svg");
boost::geometry::svg_mapper<point> mapper(svg, 400, 400);
size_t i = 0;
BOOST_FOREACH(poly& p, res)
{
std::stringstream ss;
ss << ++i * 10;
std::stringstream ss2;
ss2 << 255 - i * 10;
mapper.add(p);
mapper.map(p, "fill-opacity:0.2;fill:rgb("+ ss.str() + "," + ss2.str() +",153);stroke:rgb(0,0,200);stroke-width:2");
}
}
return 0;
}
Which produces the following output:
For this, you have to run over all combinations and compute the unions and sym_differences of the initial polygons.
Sorry, the coloring is not as nice as yours.
Does this help?

Related

Eigen indexing, update all column of a specific row

Let say I have an ArrayXXf (or MatrixXf) m. In each iteration of a for loop, I want to fill m row-wise with a VectorXf.
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++)
{
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
//fill m row wise
// in matlab I will do something like m(i,:) = vec;
// in numpy this will looks like m[i:] = vec;
// that means when i is 0 m looks like
// [ 0 1 2 3 4 5
// - - - - - -
// - - - - - -
// - - - - - -
// - - - - - -]
}
How can I achieve that in Eigen?
To simplify #Kunal's answer, you can directly modify rows (or columns) of an Array (or Matrix) without creating a temporary vector. In your example you can use .setLinSpaced():
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
m.row(i).setLinSpaced(i,i+4); //.col(i) would be slightly more efficient
}
or use the comma initializer:
for (int i = 0; i < 5; i++) {
m.row(i) << i, i+1, i+2, i+3, i+4;
}
Use block() function.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
m.block(i, 0, 1, 5) << vec.transpose();
}
std::cout << m << std::endl;
return 0;
}
Output:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
Edit:
There is one simpler alternative also: row() function.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::ArrayXXf m(5, 5);
for (int i = 0; i < 5; i++) {
Eigen::VectorXf vec(5);
vec << i, i + 1, i + 2, i+3, i+4;
m.row(i) = vec.transpose();
}
std::cout << m << std::endl;
return 0;
}
Output:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
P.S. transpose() is required because Eigen::VectorXf by default is a column vector, not a row vector.

Fill a symmetric matrix using an array

I am trying to create a symmetric matrix n x n matrix and fill it using a n*(n+1)/2 dimension array using the boost library in c++.
So far, I am able to create the matrix, and fill it with random values using the following code
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
for (unsigned i = 0; i < m_sym.size1 (); ++ i)
for (unsigned j = i; j < m_sym.size2 (); ++ j)
m_sym (i, j) = filler[i+j*m_sym.size1()];
std::cout << m_sym << std::endl;
return 0;
}
What I am trying to do is fill the upper (or lower) part of the symmetric matrix using the values from the array filler. So the output upper symmetric matrix should be
| 0 | 1 | 2 |
------------------------------------------------
0 | 0 1 3
1 | 1 2 4
2 | 3 4 5
Any idea on how to do that?
I'd simplify this a bit by just keeping an iterator that traverses filler from start to end:
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
assert(m_sym.size1() == m_sym.size2());
double const* in = std::begin(filler);
for (size_t i = 0; i < m_sym.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
m_sym (i, j) = *in++;
Prints: Live On Coliru
I'd personally suggest creating a helper function like:
Live On Wandbox
#include <iostream>
#include <fstream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace bnu = boost::numeric::ublas;
template <typename T = double>
bnu::symmetric_matrix<T, bnu::upper> make_symmetric(std::initializer_list<T> filler) {
size_t n = (sqrt(8*filler.size() + 1) - 1)/2;
assert((n*(n+1))/2 == filler.size());
bnu::symmetric_matrix<T, bnu::upper> result(n, n);
auto in = std::begin(filler);
for (size_t i = 0; i < result.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
result (i, j) = *in++;
return result;
}
int main() {
std::cout << make_symmetric({0,1,2}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5,6,7,8,9}) << "\n";
}
Prints
[2,2]((0,1),(1,2))
[3,3]((0,1,3),(1,2,4),(3,4,5))
[4,4]((0,1,3,6),(1,2,4,7),(3,4,5,8),(6,7,8,9))
Note: the size checks use the series expansion for 1 + ... + n and the inverse of that: n = 1/2 (sqrt(8 x + 1) - 1)

C++ Error in summing vector

Task:
In a 6x6 array, 16 3x3 array can be constructed. Find the largest sum of the 3x3 array (Source: https://www.hackerrank.com/challenges/30-2d-arrays/problem)
Example:
The largest 3x3 array is
2 4 4
0 2 0
1 2 4
So we print out 19
My Code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
vector< vector<int> > arr(6,vector<int>(6));
for(int arr_i = 0;arr_i < 6;arr_i++){
for(int arr_j = 0;arr_j < 6;arr_j++){
cin >> arr[arr_i][arr_j];
}
}
int maxVal = 0;
for (int y = 2; y < 6; y++)
{
for (int x = 2; x < 6; x++)
{
if ( y >=2 && x >=2)
{
int vert = y;
int hori = x;
int first = arr[vert-2][hori] + arr[vert-2][hori-1] + arr[vert-2][hori-2];
int second = arr[vert-1][hori-1] ;
int third = arr[vert][hori] + arr[vert][hori-1] + arr[vert][hori-2];
int sum = first + second + third;
if (sum > maxVal)
maxVal = sum;
}
}
}
cout << maxVal;
}
Edit:
I misunderstood the question, but I fixed the problem. Later on, I still got incorrect test-cases. The original solution seems to be wrong.
Problem: When I submit the code, some of test case return the wrong answer. I tried reading the code and nothing seems wrong.
The problem from the provided link is not about the 3x3 submatrices but about the hourglass shapes:
a b c
d
e f g
In order to get the correct values; your sum of the second row should be:
int second = arr[vert-1][hor-1]
And also, there is no need for the if statement as someone already mentioned in the comments.
Here is a cleaner code. Start from [1][1] and iterate till [length-1][length-1]. And on each iteration, calculate the sum of the surrounding hourglass.
Also, note that you need to sum the hourGlass and NOT the 3x3 subArray.
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
// user input
//vector< vector<int> > myVector(6,vector<int>(6));
//for(int arr_i = 0;arr_i < 6;arr_i++)
// for(int arr_j = 0;arr_j < 6;arr_j++)
// cin >> myVector[arr_i][arr_j];
// sample input
vector<vector<int>> myVector = {
{ { 1 },{ 1 },{ 1 },{ 0 },{ 0 },{ 0 } },
{ { 0 },{ 1 },{ 0 },{ 0 },{ 0 },{ 0 } },
{ { 1 },{ 1 },{ 1 },{ 0 },{ 0 },{ 0 } },
{ { 0 },{ 0 },{ 2 },{ 4 },{ 4 },{ 0 } },
{ { 0 },{ 0 },{ 0 },{ 2 },{ 0 },{ 0 } },
{ { 0 },{ 0 },{ 1 },{ 2 },{ 4 },{ 0 } },
};
int maxVal = -9999; // start with big negative
for (int y = 1; y < 5; y++)
{
int sum = 0;
for (int x = 1; x < 5; x++)
{
sum = myVector[y - 1][x - 1] + myVector[y - 1][x] + myVector[y - 1][x + 1]; // first row of the hourglass
sum += myVector[y][x]; // second row
sum += myVector[y + 1][x - 1] + myVector[y + 1][x] + myVector[y + 1][x + 1];// third row
if (sum > maxVal)
maxVal = sum;
}
}
cout << maxVal << endl;
system("pause");
return 0;
}
Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
int main(){
int arr[7][7], sum[17], l = 0;
for (int i = 0; i < 6; i++){
for (int j = 0; j < 6; j++){
cin >> arr[i][j];
}
}
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
sum[l] = 0;
sum[l] = sum[l] + arr[i][j] + arr[i][j+1] + arr[i][j+2] + arr[i+1][j] + arr[i+1][j+1] + arr[i+1][j+2]+ arr[i+2][j] + arr[i+2][j+1] + arr[i+2][j+2];
l++;
}
}
sort(sum, sum + 17);
cout << sum[16];
}
Explanation
This is a simple problem with small values, so we do not need dynamic programming(YAY!).
Vectors are also quite useless here when we can do it correctly with arrays.
Basically I search every set of 3x3 squares, and find the maximum sum. Hope this helps!

feeding hex characters to stringstream

I'm trying to set bits in a binary string. I initially have an empty string which needs to set the give bit(i) in the string(s).
for the given example, the output should be 0x3001 as:
pos: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
bit: 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1
^ ^
MSB LSB
Which, in hex is 3001.
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
void generate_string(string& s,int i){
int sl = s.length();
int x = i/8;
std::stringstream m(s, ios_base::app);
if(sl<x){
for(int j = x-sl;j>=0;j--){
m<<'\x00';
}
}
s = m.str();
s[x] |= 1 << i%8;
}
int main(){
string s = "";
generate_string(s,15);
generate_string(s,2);
generate_string(s,3);
for(int i=0;i<s.length();i++)
cout<<hex<<(int)s[i];
return 0;
}
But this program is not showing any output.
It's actually much more simpler than you think. The only complicated part is to calculate the bit number to be set in the byte.
Oh, and why use a string for this? Why not a vector?
Here's my solution, using std::vector instead:
void set_bit(std::vector<uint8_t>& bits, unsigned bit)
{
static unsigned const bit_count = 8; // Should really use std::numeric_limits<uint8_t>::digits
unsigned index = bit / bit_count;
while (index + 1 > bits.size())
bits.push_back(0);
// Since the bit-numbers are reversed from what's "common",
// we need a little more complex calculation here.
// bit % bit_count to get the "normal" bit number
// bit_count - bit % bit_count to reverse the bit numbering
// Then -1 to get a number between 0 and 7
bits[index] |= 1 << (bit_count - bit % bit_count - 1);
}
You can use a similar solution using std::string too, but I don't see why.
Maybe like this?
#include<iostream>
#include<string>
using namespace std;
void set_bit(string& s,int i){
auto bits = ((i + 7) / 8) * 8;
if (bits > s.length())
{
auto diff = bits - s.length();
s += std::string(diff, '0');
}
s[i] = '1';
}
int main(){
string s;
set_bit(s, 2);
set_bit(s, 3);
set_bit(s, 15);
cout << s << endl;
return 0;
}
expected output:
0011000000000001
update: attempt 2 :-)
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
void set_bit(string& s,int i){
auto bytes = (i + 7) / 8;
if (bytes > s.length())
{
auto diff = bytes - s.length();
s += std::string(diff, 0);
}
s[i / 8] |= char(1 << (7-(i%8)));
}
int main(){
string s;
set_bit(s, 2);
set_bit(s, 3);
set_bit(s, 15);
std::cout << "as hex: ";
for (auto c : s) {
cout << hex << setfill('0') << setw(2) << (int(c) & 0xff);
}
cout << endl;
std::cout << "as binary: ";
auto sep = "";
for (auto c : s) {
unsigned char bits = c;
for (unsigned char mask = 0x80 ; mask ; mask >>= 1)
{
cout << sep << ((bits & mask) ? '1' : '0');
sep = " ";
}
}
cout << endl;
return 0;
}
expected output:
as hex: 3001
as binary: 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1
I don't quite understand what the output should be in Your problem, because You are mixing most/least signifanct bits with nibbles order in sample input/output, but I You would like to print number in hex as a string You can do sth like this:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
void feed(std::string& s, int x){
unsigned int mask = 15;
int nibblesInWord = sizeof(void*)*16;
std::stringstream ss;
while(nibblesInWord--){
std::cout << int(x & mask) <<std::endl;
ss << int(x & mask);
x >>= 4;
}
s = ss.str();
std::reverse(s.begin(), s.end());
}
int main(){
std::string s;
feed(s, 99);
std::cout << s <<std::endl;
}

Dijkstra's Algorithm , C++, Priority Queue, Adjacency List

#include <iostream>
#include <fstream>
#include <functional>
#include <climits>
#include <vector>
#include <queue>
#include <list>
using namespace std;
struct Vertices {
int vertex;
int weight;
Vertices(int v, int w) : vertex(v), weight(w) { };
Vertices() { }
};
class CompareGreater {
public:
bool const operator()(Vertices &nodeX, Vertices &nodeY) {
return (nodeX.weight > nodeY.weight) ;
}
};
vector< list<Vertices> > adj;
vector<int> weights;
priority_queue<Vertices, vector<Vertices>, CompareGreater> Q;
int nrVertices, nrEdges;
void Dijkstra(Vertices);
void makeGraph() {
ifstream myFile;
myFile.open("graph.txt");
myFile >> nrVertices >> nrEdges;
adj.resize(nrVertices+1);
int nodeX, nodeY, weight;
for (int i = 1; i <= nrVertices; ++i) {
weights.push_back(INT_MAX);
}
for (int i = 1; i <= nrEdges; ++i) {
myFile >> nodeX >> nodeY >> weight;
adj[nodeX].push_back(Vertices(nodeY, weight));
}
}
void printPath()
{
for (vector<int>::iterator itr = weights.begin()+1; itr != weights.end(); ++itr) {
cout << (*itr) << " "<<endl;
}
}
void Dijkstra(Vertices startNode) {
Vertices currVertex;
weights[startNode.vertex] = 0;
Q.push(startNode);
while (!Q.empty()) {
currVertex = Q.top();
Q.pop();
cout<<"Removed "<<&currVertex<<"from heap"<<endl;
if (currVertex.weight <= weights[currVertex.vertex]) {
for (list<Vertices>::iterator it = adj[currVertex.vertex].begin(); it != adj[currVertex.vertex].end(); ++it)
{
if (weights[it->vertex] > weights[currVertex.vertex] + it->weight) {
weights[it->vertex] = weights[currVertex.vertex] + it->weight;
Q.push(Vertices((it->vertex), weights[it->vertex]));
}
}
}
}
}
int main() {
makeGraph();
Dijkstra(Vertices(1, 0));
printPath();
return 0;
}
So this is my code to implement Dijkstra's algorithm with an adjacency list. With input:
7
2
2 2
4 1
2
4 3
5 10
2
1 4
6 5
4
3 2
5 2
6 8
7 4
1
7 6
0
1
6 1
This means that there exists 7 vertices in order from vertex 1 to 7. Vertex 1 has 2 edges, one to vertex 2 with weight 2, the second to vertex 4 with weight 1. Vertex 2 has 2 edges, the first to vertex 4 with weight 3, the second to vertex 5 with weight 10. Vertex 3 has 2 edges, the first to vertex 1 with weight 4, the second to vertex 6 with weight 5. And so forth.
However, it print out this:
Removed 0xbfb9d7a8from heap
Removed 0xbfb9d7a8from heap
0
4
2147483647
2147483647
2147483647
2147483647
When I need it to print out this:
V1: V2, 2; V4, 1
V2: v4, 3; V5, 10
V3: V1, 4; V6, 5
V4: V3, 2; V5, 2; V6, 8; V7, 4
V5: V7, 6
V6:
V7: V6, 1
Removed minimum 1 from heap
Print heap: V2, d=inf V4., d=inf v3, d= inf v7, d=inf v5......
Please help!!!!!