Following this: How to print the faces of a Voronoi diagram?, I now have:
#include <iostream>
#include <fstream>
#include <cassert>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Segment_Delaunay_graph_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_policies_2.h>
#include <CGAL/Segment_Delaunay_graph_traits_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Segment_Delaunay_graph_traits_2<K> Gt;
typedef CGAL::Segment_Delaunay_graph_2<Gt> DT;
int main() {
std::ifstream ifs("data.cin");
assert( ifs );
DT vd;
DT::Site_2 site;
// read the sites from the stream and insert them in the diagram
while ( ifs >> site ) { vd.insert( site ); }
ifs.close();
// validate the diagram
assert( vd.is_valid(true, 1) );
std::cout << std::endl << std::endl;
// Iterate over edges
DT::Finite_edges_iterator eit = vd.finite_edges_begin();
for (int k = 1; eit != vd.finite_edges_end(); ++eit, ++k) {
DT::Edge e = *eit;
//std::cout << e << std::endl;
}
}
However, an edge cannot be printed that simply (with cout). How to do it?
Here is the error from another attempt:
/home/gsamaras/CGAL-4.7/code/DelaunayTOvoronoi/delTovor.cpp:30:27: error: ‘CGAL::Triangulation_ds_edge_iterator_2<CGAL::Triangulation_data_structure_2<CGAL::Segment_Delaunay_graph_vertex_base_2<CGAL::Segment_Delaunay_graph_storage_traits_2<CGAL::Segment_Delaunay_graph_traits_2<CGAL::Epick> >, CGAL::Triangulation_ds_vertex_base_2<void> >, CGAL::Segment_Delaunay_graph_face_base_2<CGAL::Segment_Delaunay_graph_traits_2<CGAL::Epick>, CGAL::Triangulation_ds_face_base_2<void> > >, true>::Edge’ has no member named ‘site’
std::cout << eit->site() << std::endl;
^
You can print the sites forming the edge like this:
for (int k = 1; eit != vd.finite_edges_end(); ++eit, ++k) {
DT::Edge e = *eit;
std::cout << "k = " << k << std::endl;
if ( vd.is_infinite(e.first->vertex( vd.ccw(e.second) )) )
std::cout << "infinite\n";
else
std::cout << e.first->vertex( vd.ccw(e.second) )->site() << std::endl;
if ( vd.is_infinite(e.first->vertex( vd.cw(e.second) )) )
std::cout << "infinite\n";
else
std::cout << e.first->vertex( vd.cw(e.second) )->site() << std::endl;
if ( vd.is_infinite(e.first->vertex( e.second )) )
std::cout << "infinite\n";
else
std::cout << e.first->vertex( e.second )->site() << std::endl;
if ( vd.is_infinite(vd.tds().mirror_vertex(e.first, e.second) ) )
std::cout << "infinite\n";
else
std::cout << vd.tds().mirror_vertex(e.first, e.second)->site() << std::endl;
}
Related
I'm using CGAL (v. 4.14-2) to compute the visibility region (polygon) within a simple polygon from one of its vertices, using the Simple_polygon_visibility_2 class.
On a particular combination of polygon/vertex, I'm getting the following assertion error:
terminate called after throwing an instance of 'CGAL::Assertion_exception'
what(): CGAL ERROR: assertion violation!
Expr: k+1<vertices.size()
File: /usr/include/CGAL/Simple_polygon_visibility_2.h
Line: 678
This occurs in the method scan_edges of the class Simple_polygon_visibility_2, it seems like there should be some intersection with the given segment/ray, but none was found.
When I run the same code with the class Triangular_expansion_visibility_2, it seems to work, giving the output:
Regularized visibility region of q has 8 edges:
[7968 492 -> 7938 428]
[7884 408 -> 7968 492]
[8040 428 -> 7884 408]
[8090.99 428 -> 8040 428]
[8105.55 458.865 -> 8090.99 428]
[8090 456 -> 8105.55 458.865]
[7968 446 -> 8090 456]
[7938 428 -> 7968 446]
Here's a minimal working example:
#include <CGAL/Arr_naive_point_location.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/Simple_polygon_visibility_2.h>
#include <CGAL/Triangular_expansion_visibility_2.h>
#include <fstream>
#include <iostream>
#include <string>
#include <list>
#include <vector>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
typedef CGAL::Polygon_2<Kernel, std::list<Point_2>> Polygon_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Traits_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
typedef Arrangement_2::Vertex_handle ArrVertex_handle;
typedef Arrangement_2::Edge_const_iterator Edge_const_iterator;
typedef Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator;
using namespace std;
vector<Point_2> readInput() {
vector<Point_2> Points;
ifstream File;
File.open("polygon");
string Line;
long int Idx, XCoord, YCoord;
while (getline(File, Line)) {
istringstream Iss(Line);
Iss >> Idx >> XCoord >> YCoord;
Points.push_back({XCoord, YCoord});
}
return Points;
}
int main() {
// create environment
std::vector<Segment_2> segments;
Arrangement_2 env;
Segment_2 CurrSegment;
Polygon_2 AuxPoly;
auto Points = readInput();
auto QueryPt = Points[0];
ArrVertex_handle CurrPtHandle =
env.insert_in_face_interior(QueryPt, env.unbounded_face());
AuxPoly.push_back(Points[0]);
ArrVertex_handle NextPtHandle = CurrPtHandle;
ArrVertex_handle QueryPtHandle = CurrPtHandle;
for (auto i = 1; i < Points.size(); ++i) {
NextPtHandle = env.insert_in_face_interior(Points[i], env.unbounded_face());
CurrSegment = Segment_2(CurrPtHandle->point(), NextPtHandle->point());
env.insert_at_vertices(CurrSegment, CurrPtHandle, NextPtHandle);
CurrPtHandle = NextPtHandle;
AuxPoly.push_back(Points[i]);
}
assert(AuxPoly.is_simple());
CurrSegment = Segment_2(CurrPtHandle->point(), QueryPtHandle->point());
auto HalfEHandle =
env.insert_at_vertices(CurrSegment, CurrPtHandle, QueryPtHandle);
if (HalfEHandle->face()->is_unbounded()) {
// there are exactly two incident halfedges in the query point
auto FirstHalfE = HalfEHandle->target()->incident_halfedges();
HalfEHandle = (FirstHalfE != HalfEHandle) ? FirstHalfE : next(FirstHalfE, 1);
}
// compute non regularized visibility area
// Define visibiliy object type that computes regularized visibility area
typedef CGAL::Simple_polygon_visibility_2<Arrangement_2, CGAL::Tag_true> RSPV;
// typedef CGAL::Triangular_expansion_visibility_2<Arrangement_2, CGAL::Tag_true> RSPV;
Arrangement_2 regular_output;
RSPV regular_visibility(env);
regular_visibility.compute_visibility(QueryPtHandle->point(), HalfEHandle, regular_output);
std::cout << "Regularized visibility region of q has "
<< regular_output.number_of_edges() << " edges:" << std::endl;
for (Edge_const_iterator eit = regular_output.edges_begin();
eit != regular_output.edges_end(); ++eit)
std::cout << "[" << eit->source()->point() << " -> "
<< eit->target()->point() << "]" << std::endl;
return 0;
}
an auxiliary file arr_print.h to print the arrangement:
#ifndef _PRINT_ARR_H_
#define _PRINT_ARR_H_
#include <iostream>
//-----------------------------------------------------------------------------
// Print all neighboring vertices to a given arrangement vertex.
//
template<class Arrangement>
void print_neighboring_vertices (typename Arrangement::Vertex_const_handle v)
{
if (v->is_isolated())
{
std::cout << "The vertex (" << v->point() << ") is isolated" << std::endl;
return;
}
typename Arrangement::Halfedge_around_vertex_const_circulator first, curr;
typename Arrangement::Vertex_const_handle u;
std::cout << "The neighbors of the vertex (" << v->point() << ") are:";
first = curr = v->incident_halfedges();
do
{
// Note that the current halfedge is (u -> v):
u = curr->source();
std::cout << " (" << u->point() << ")";
++curr;
} while (curr != first);
std::cout << std::endl;
return;
}
//-----------------------------------------------------------------------------
// Print all vertices (points) and edges (curves) along a connected component
// boundary.
//
template<class Arrangement>
void print_ccb (typename Arrangement::Ccb_halfedge_const_circulator circ)
{
typename Arrangement::Ccb_halfedge_const_circulator curr = circ;
typename Arrangement::Halfedge_const_handle he;
std::cout << "(" << curr->source()->point() << ")";
do
{
he = curr;
std::cout << " [" << he->curve() << "] "
<< "(" << he->target()->point() << ")";
++curr;
} while (curr != circ);
std::cout << std::endl;
return;
}
//-----------------------------------------------------------------------------
// Print the boundary description of an arrangement face.
//
template<class Arrangement>
void print_face (typename Arrangement::Face_const_handle f)
{
// Print the outer boundary.
if (f->is_unbounded())
{
std::cout << "Unbounded face. " << std::endl;
}
else
{
std::cout << "Outer boundary: ";
print_ccb<Arrangement> (f->outer_ccb());
}
// Print the boundary of each of the holes.
typename Arrangement::Hole_const_iterator hole;
int index = 1;
for (hole = f->holes_begin(); hole != f->holes_end(); ++hole, ++index)
{
std::cout << " Hole #" << index << ": ";
print_ccb<Arrangement> (*hole);
}
// Print the isolated vertices.
typename Arrangement::Isolated_vertex_const_iterator iv;
for (iv = f->isolated_vertices_begin(), index = 1;
iv != f->isolated_vertices_end(); ++iv, ++index)
{
std::cout << " Isolated vertex #" << index << ": "
<< "(" << iv->point() << ")" << std::endl;
}
return;
}
//-----------------------------------------------------------------------------
// Print the given arrangement.
//
template<class Arrangement>
void print_arrangement (const Arrangement& arr)
{
// CGAL_precondition (arr.is_valid());
// Print the arrangement vertices.
typename Arrangement::Vertex_const_iterator vit;
std::cout << arr.number_of_vertices() << " vertices:" << std::endl;
for (vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit)
{
std::cout << "(" << vit->point() << ")";
if (vit->is_isolated())
std::cout << " - Isolated." << std::endl;
else
std::cout << " - degree " << vit->degree() << std::endl;
}
// Print the arrangement edges.
typename Arrangement::Edge_const_iterator eit;
std::cout << arr.number_of_edges() << " edges:" << std::endl;
for (eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
std::cout << "[" << eit->curve() << "]" << std::endl;
// Print the arrangement faces.
typename Arrangement::Face_const_iterator fit;
std::cout << arr.number_of_faces() << " faces:" << std::endl;
for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
print_face<Arrangement> (fit);
return;
}
#endif
The input polygon:
input polygon
The input file has in each line the polygon vertex id, followed by its x- and-coordinates. The query point is the one with id 1716.
Could anyone help me with this issue?
Thank you all in advance.
NOTE: See edit at the bottom of this post for code that solves my problem.
I am constructing a Voronoi diagram in CGAL. Each site in my diagram has some non-geometric information associated with it (like the population of a city, or the temperature at a certain location). After I construct the Voronoi diagram, I will perform location queries on it, and I will need to be able to recover this non-geometric information from the query results. It seems that CGAL has the capability to do this; this is discussed for example here in the context of Delaunay triangulations. But I cannot figure out how to apply this technique for Voronoi diagrams. Here's what I tried, which fails to compile:
Broken code removed. See working code example below.
Remainder of question deleted, since it pertains to deleted, broken code. See working code example below.
EDIT 1: Fixed errors pointed pointed out by sloriot, and included complete compiler output.
EDIT 2: In a comment, Dr. Fabri suggested that I start by modifying the CGAL example vd_2_point_location.cpp. Following his advice, I here post a working code. This is a very lightly modified version of vd_2_point_location.cpp.
// standard includes
#include <iostream>
#include <fstream>
#include <cassert>
// includes for defining the Voronoi diagram adaptor
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Voronoi_diagram_2.h>
#include <CGAL/Delaunay_triangulation_adaptation_traits_2.h>
#include <CGAL/Delaunay_triangulation_adaptation_policies_2.h>
// typedefs for defining the adaptor
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_with_info_2<int, K> VB;
typedef CGAL::Triangulation_data_structure_2<VB> TDS;
typedef CGAL::Delaunay_triangulation_2<K,TDS> DT;
typedef CGAL::Delaunay_triangulation_adaptation_traits_2<DT> AT;
typedef CGAL::Delaunay_triangulation_caching_degeneracy_removal_policy_2<DT> AP;
typedef CGAL::Voronoi_diagram_2<DT,AT,AP> VD;
// typedef for the result type of the point location
typedef AT::Site_2 Site_2;
typedef AT::Point_2 Point_2;
typedef VD::Locate_result Locate_result;
typedef VD::Vertex_handle Vertex_handle;
typedef VD::Face_handle Face_handle;
typedef VD::Halfedge_handle Halfedge_handle;
typedef VD::Ccb_halfedge_circulator Ccb_halfedge_circulator;
void print_endpoint(Halfedge_handle e, bool is_src) {
std::cout << "\t";
if ( is_src ) {
if ( e->has_source() ) std::cout << e->source()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
} else {
if ( e->has_target() ) std::cout << e->target()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
}
}
int main()
{
std::ifstream ifs("data/data1.dt.cin");
assert( ifs );
VD vd;
Site_2 t;
int ctr=0;
while ( ifs >> t ) {
Face_handle fh = vd.insert(t); // Add the site...
fh->dual()->info() = ctr++; // ...attach some info to it
}
ifs.close();
assert( vd.is_valid() );
std::ifstream ifq("data/queries1.dt.cin");
assert( ifq );
Point_2 p;
while ( ifq >> p ) {
std::cout << "Query point (" << p.x() << "," << p.y()
<< ") lies on a Voronoi " << std::flush;
Locate_result lr = vd.locate(p);
if ( Vertex_handle* v = boost::get<Vertex_handle>(&lr) ) {
std::cout << "vertex." << std::endl;
std::cout << "The Voronoi vertex is:" << std::endl;
std::cout << "\t" << (*v)->point() << std::endl;
} else if ( Halfedge_handle* e = boost::get<Halfedge_handle>(&lr) ) {
std::cout << "edge." << std::endl;
std::cout << "The source and target vertices "
<< "of the Voronoi edge are:" << std::endl;
print_endpoint(*e, true);
print_endpoint(*e, false);
} else if ( Face_handle* f = boost::get<Face_handle>(&lr) ) {
std::cout << "face." << std::endl;
std::cout << "The info associated with this face is "
<< (*f)->dual()->info() << std::endl;
std::cout << "The vertices of the Voronoi face are"
<< " (in counterclockwise order):" << std::endl;
Ccb_halfedge_circulator ec_start = (*f)->ccb();
Ccb_halfedge_circulator ec = ec_start;
do {
print_endpoint(ec, false);
} while ( ++ec != ec_start );
}
std::cout << std::endl;
}
ifq.close();
return 0;
}
I am trying to subtract the 1st element of the std::map from every other element of that same std::map. I couldn't find anything about that. Is it possible? for example :
std::map<char,int> bar;
bar['a']=11; //should be deleted from other elements
bar['b']=22;
bar['c']=33;
bar['d']=44;
std::cout << "bar contains:\n";
for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
{
std::cout <<"key: " <<it->first << " Value=> " << it->second << '\n'; //can i delete here??
//i want to delete value of a from value of b and update the value of b
}
//the new map should be look like as follows
//bar['a']=11; //or may be 0
//bar['b']=11;
//bar['c']=22;
//bar['d']=33;
Any ideas to do it easily with map in c++?
Thanks.
C++11 Solution
You could use std::for_each for this
std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });
For example
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
int main()
{
std::map<char,int> bar;
bar['a']=11;
bar['b']=22;
bar['c']=33;
bar['d']=44;
std::for_each(std::next(bar.begin()), bar.end(), [&bar](std::pair<const char, int>& x){ x.second -= bar.begin()->second; });
std::cout << "bar contains:\n";
for (std::map<char,int>::iterator it=bar.begin(); it!=bar.end(); ++it)
{
std::cout << "key: " << it->first << " Value=> " << it->second << '\n';
}
}
Output (working demo)
bar contains:
key: a Value=> 11
key: b Value=> 11
key: c Value=> 22
key: d Value=> 33
And if you want to subtract even the first element from itself, just remove the std::next call and capture the value you want to subtract out, since you're going to modify the first map entry.
auto const sub = bar.begin()->second;
std::for_each(bar.begin(), bar.end(), [&sub](std::pair<const char, int>& x){ x.second -= sub; });
C++03 Solution
To subtract the first element from everything except the first element itself
int value = bar.begin()->second;
std::map<char, int>::iterator it = bar.begin();
std::advance(it, 1);
for (; it != bar.end(); ++it)
{
it->second -= value;
}
To include the first element
int value = bar.begin()->second;
for (std::map<char, int>::iterator it = bar.begin(); it != bar.end(); ++it)
{
it->second -= value;
}
You simply need to loop over the map and subtract the value associated with the "first" key from each element, storing the result back into the same element. One approach to that is shown below:
Live example at http://coliru.stacked-crooked.com/a/1bc650592027f5f3
#include <iostream>
#include <map>
int main() {
// Set up the problem...
std::map<char, int> foo;
foo['a'] = 11;
foo['b'] = 22;
foo['c'] = 33;
foo['d'] = 44;
// Obtain the value of the 'a' key...
const int value = foo['a'];
// Subtract that value from each element...
for (auto& element : foo) {
element.second -= value;
}
// Output the map to verify the result...
for (auto& element : foo) {
std::cout << element.first << ": " << element.second << "\n";
}
return 0;
}
Note that if you loop over the entire map, you need to store the initial value of foo[a], since you'll zero it during the iterative subtraction. You can avoid this by using iterators and skipping over the first element using e.g. std::next(foo.begin()). Other answers demonstrate this technique, so I won't duplicate it here.
You can use standard algorithm std::for_each declared in header <algorithm>
If your compiler supports C++ 2014 then the code can look like
#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
std::for_each( std::next( bar.begin() ), bar.end(),
[value = ( *bar.begin() ).second] ( auto &p ) { p.second -= value; } );
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
The program output is
{ a, 11 } { b, 22 } { c, 33 } { d, 44 }
{ a, 11 } { b, 11 } { c, 22 } { d, 33 }
If your compiler supports only C++ 2011 then the main loop in the program can look like
if ( !bar.empty() )
{
auto value = ( *bar.begin() ).second;
std::for_each( std::next( bar.begin() ), bar.end(),
[value] ( std::pair<const char, int> &p ) { p.second -= value; } );
}
The same can be done using for example the range based for loop
#include <iostream>
#include <map>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
auto value = ( *bar.begin() ).second;
bool first = true;
for ( auto &p : bar )
{
if ( first ) first = !first;
else p.second -= value;
}
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
Also if the element by which all other elements should be decreased is not necessary the first element of the map then you can use the following approach
#include <iostream>
#include <map>
#include <algorithm>
#include <iterator>
int main()
{
std::map<char, int> bar;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
bar['d'] = 44;
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
if ( !bar.empty() )
{
// the initializer can be any element not only the first one
const auto &value = *bar.begin();
for ( auto &p : bar )
{
if ( p.first != value.first ) p.second -= value.second;
}
}
for ( const auto &p : bar )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
}
int value = bar.begin()->second;
for(std::map<char,int>::reverse_iterator it=bar.rbegin(); it != bar.rend(); it++) {
it->second -= bar.begin()->second;
}
bar.begin()->second = value;
I have to print out the size of the vector and all the contents inside it. But my for loop doesnt iterate, it doesn't go up by one but instead stays at the value 0 for the whole loop.
#include "stdafx.h"
#include <string.h>
#include <string>
#include <iostream>
#include <cctype>
#include <vector>
#include <list>
using std::string;
using std::vector;
vector<int> v2(10);
for( auto i : v2)
{
if( i == 0 )
{
std::cout << v2.size() << std::endl;
}
std::cout << "Element value " << (i) << " is " << v2[i] << std::endl;
}
So I only want to print the size once, at the start. Then print out each element value which I know will be 0 by default. But it just prints out "Element value 0 is 0" 9 times.
If you want at first to print out the size of the vector then place this output statement before the range based for statement
std::vector<int> v2(10);
std::cout << v2.size() << std::endl;
size_t i = 0;
for ( auto x : v2 )
{
std::cout << "Element value " << i++ << " is " << x << std::endl;
}
But if you are using a count then it would be better to use the ordinary for statement
std::vector<int> v2(10);
std::cout << v2.size() << std::endl;
for ( std::vector<int>::size_type i = 0; i < v2.size(); i++ )
{
std::cout << "Element value " << i << " is " << v2[i] << std::endl;
}
Your question indicates that you want to treat the first element differently. This does not work with range-based for loops out of the box. You have two options:
Use an extra variable to remember whether the first iteration was made.
Use a traditional loop, using an index variable or an iterator.
Example for 1:
bool first_iteration = true;
for( auto i : v2)
{
if (first_iteration)
{
std::cout << v2.size() << std::endl;
first_iteration = false;
}
// ...
}
Example for 2:
for (auto iter = v2.begin(); iter != v2.end(); ++iter)
{
if (iter == v2.begin())
{
std::cout << v2.size() << std::endl;
}
// ...
}
First part of the question is that I am trying to use boost::bimap, but from the documentation it is unclear to me how to define a bidirectional multimap.
The second part of the question is that I need it to be a map in one direction and a multimap in the other direction, can this be done using boost::bimap ?
Has anyone experience of this or can point me to the correct page ?
All is in documentation... http://www.boost.org/doc/libs/1_51_0/libs/bimap/doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html
typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;
Example.
#include <iostream>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
namespace bimaps = boost::bimaps;
int main()
{
typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;
typedef bimap_t::value_type value_type;
bimap_t bimap;
bimap.insert(value_type(1, 1));
bimap.insert(value_type(1, 2));
auto& left = bimap.left;
auto it = left.find(1);
std::cout << "LEFT" << std::endl;
for (; it != left.end(); ++it)
{
std::cout << it->first << " " << it->second << std::endl;
}
auto& right = bimap.right;
auto r_it = right.find(2);
std::cout << "RIGHT" << std::endl;
for (; r_it != right.end(); ++r_it)
{
std::cout << r_it->first << " " << r_it->second << std::endl;
}
}
The answer from ForEverR is partially correct for the first part of your question (how to define a bidirectional multimap?).
For the second part (accessing a bimap which is a map in one direction and a multimap in the other direction) It is not correct.
A correct way to access would be [ http://rextester.com/BXBDHN12336 ]:
//bimap operations
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
int main()
{
typedef boost::bimap<boost::bimaps::multiset_of<int>, boost::bimaps::set_of<int>> bimap_t;
typedef bimap_t::value_type value_type;
bimap_t bimap;
bimap.insert(value_type(1, 1));
bimap.insert(value_type(10, 50));
bimap.insert(value_type(1, 2));
bimap.insert(value_type(9, 15));
typedef bimap_t::left_const_iterator l_itr_t;
typedef std::pair<l_itr_t,l_itr_t> l_itr_range_t;
l_itr_range_t ii = bimap.left.equal_range(1);
std::cout << "LEFT" << std::endl;
for(l_itr_t it = ii.first; it != ii.second; ++it)
{
std::cout << "Key = " << it->first << " Value = " << it->second << std::endl;
}
std::cout << "RIGHT" << std::endl;
std::cout << "Key = " << 1 << " Value = " << bimap.right.at(1) << std::endl;
}
stdout:
LEFT
Key = 1 Value = 1
Key = 1 Value = 2
RIGHT
Key = 1 Value = 1
The example from ForEverR 'seems' to work because of the order of the data inserted but check out the results when you insert another couple at the end bimap.insert(value_type(9, 15));:
#include <iostream>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
namespace bimaps = boost::bimaps;
int main()
{
typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;
typedef bimap_t::value_type value_type;
bimap_t bimap;
bimap.insert(value_type(1, 1));
bimap.insert(value_type(1, 2));
bimap.insert(value_type(9, 15));
auto& left = bimap.left;
auto it = left.find(1);
std::cout << "LEFT" << std::endl;
for (; it != left.end(); ++it)
{
std::cout << it->first << " " << it->second << std::endl;
}
auto& right = bimap.right;
auto r_it = right.find(2);
std::cout << "RIGHT" << std::endl;
for (; r_it != right.end(); ++r_it)
{
std::cout << r_it->first << " " << r_it->second << std::endl;
}
}
stdout:
LEFT
1 1
1 2
9 15
RIGHT
2 1
15 9