File GeometrySet.h
File List > detail > GeometrySet.h
Go to the documentation of this file
// Copyright (c) 2012-2013, IGN France.
// Copyright (c) 2012-2022, Oslandia.
// SPDX-License-Identifier: LGPL-2.0-or-later
#ifndef _SFCGAL_DETAIL_GEOMETRY_SET_H_
#define _SFCGAL_DETAIL_GEOMETRY_SET_H_
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/variant.hpp>
#include "SFCGAL/config.h"
#include "SFCGAL/Kernel.h"
#include "SFCGAL/detail/TypeForDimension.h"
#include <CGAL/Bbox_2.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/Box_intersection_d/Box_with_handle_d.h>
// comparison operator on segments, for use in a std::set
bool
operator<(const CGAL::Segment_2<SFCGAL::Kernel> &sega,
const CGAL::Segment_2<SFCGAL::Kernel> &segb);
bool
operator<(const CGAL::Segment_3<SFCGAL::Kernel> &sega,
const CGAL::Segment_3<SFCGAL::Kernel> &segb);
namespace SFCGAL {
class Geometry;
namespace detail {
enum PrimitiveType {
PrimitivePoint = 0,
PrimitiveSegment = 1,
PrimitiveSurface = 2,
PrimitiveVolume = 3
};
template <int Dim>
struct PrimitiveHandle {
//
// We use boost::variant here for convenience, whereas it is needed
typedef boost::variant<const typename Point_d<Dim>::Type *,
const typename Segment_d<Dim>::Type *,
const typename Surface_d<Dim>::Type *,
const typename Volume_d<Dim>::Type *>
Type;
Type handle;
template <class T>
PrimitiveHandle(const T *p) : handle(p)
{
}
template <class T>
inline const T *
as() const
{
return boost::get<const T *>(handle);
}
};
template <int Dim>
struct PrimitiveBox {
typedef CGAL::Box_intersection_d::Box_with_handle_d<double, Dim,
PrimitiveHandle<Dim> *>
Type;
};
template <int Dim>
struct BoxCollection {
typedef std::vector<typename PrimitiveBox<Dim>::Type> Type;
};
template <int Dim>
struct HandleCollection {
typedef std::list<PrimitiveHandle<Dim>> Type;
};
enum ElementFlag {
// the polyhedron is planar => build a triangle or a polygon
FLAG_IS_PLANAR = 1
};
template <class Primitive>
class CollectionElement {
public:
int
flags() const
{
return _flags;
}
void
setFlags(int flags)
{
_flags = flags;
}
Primitive &
primitive()
{
return _primitive;
}
const Primitive &
primitive() const
{
return _primitive;
}
// constructor from Primitive
CollectionElement() : _flags(0) {}
CollectionElement(const Primitive &p) : _primitive(p), _flags(0) {}
CollectionElement(const Primitive &p, int f) : _primitive(p), _flags(f) {}
CollectionElement(const CollectionElement &other)
: _primitive(other._primitive), _flags(other._flags)
{
}
bool
operator<(const CollectionElement &other) const
{
return _primitive < other._primitive;
}
private:
Primitive _primitive;
int _flags;
};
template <class Primitive>
std::ostream &
operator<<(std::ostream &ostr, const CollectionElement<Primitive> &p)
{
ostr << p.primitive() << " flags: " << p.flags();
return ostr;
}
template <int Dim>
class GeometrySet {
public:
// Points are stored in an ordered set
typedef std::set<CollectionElement<typename Point_d<Dim>::Type>>
PointCollection;
// Segments are stored in an ordered set
typedef std::set<CollectionElement<typename Segment_d<Dim>::Type>>
SegmentCollection;
typedef std::list<CollectionElement<typename Surface_d<Dim>::Type>>
SurfaceCollection;
typedef std::list<CollectionElement<typename Volume_d<Dim>::Type>>
VolumeCollection;
GeometrySet();
GeometrySet(const Geometry &g);
GeometrySet(const typename TypeForDimension<Dim>::Point &g, int flags = 0);
GeometrySet(const typename TypeForDimension<Dim>::Segment &g, int flags = 0);
GeometrySet(const typename TypeForDimension<Dim>::Surface &g, int flags = 0);
GeometrySet(const typename TypeForDimension<Dim>::Volume &g, int flags = 0);
void
merge(const GeometrySet<Dim> &g);
void
addGeometry(const Geometry &g);
void
addPrimitive(const PrimitiveHandle<Dim> &p);
void
addPrimitive(const CGAL::Object &o, bool pointsAsRing = false);
void
addPrimitive(const typename TypeForDimension<Dim>::Point &g, int flags = 0);
template <class IT>
void
addPoints(IT ibegin, IT iend)
{
std::copy(ibegin, iend, std::inserter(_points, _points.end()));
}
void
collectPoints(const PrimitiveHandle<Dim> &b);
void
addPrimitive(const typename TypeForDimension<Dim>::Segment &g, int flags = 0);
template <class IT>
void
addSegments(IT ibegin, IT iend)
{
std::copy(ibegin, iend, std::inserter(_segments, _segments.end()));
}
void
addPrimitive(const typename TypeForDimension<Dim>::Surface &g, int flags = 0);
template <class IT>
void
addSurfaces(IT ibegin, IT iend)
{
std::copy(ibegin, iend, std::back_inserter(_surfaces));
}
void
addPrimitive(const typename TypeForDimension<Dim>::Volume &g, int flags = 0);
template <class IT>
void
addVolumes(IT ibegin, IT iend)
{
std::copy(ibegin, iend, std::back_inserter(_volumes));
}
int
dimension() const;
void
addBoundary(const typename TypeForDimension<Dim>::Surface &surface);
void
addBoundary(const typename TypeForDimension<Dim>::Volume &volume);
void
computeBoundingBoxes(typename HandleCollection<Dim>::Type &handles,
typename BoxCollection<Dim>::Type &boxes) const;
inline PointCollection &
points()
{
return _points;
}
inline const PointCollection &
points() const
{
return _points;
}
inline SegmentCollection &
segments()
{
return _segments;
}
inline const SegmentCollection &
segments() const
{
return _segments;
}
inline SurfaceCollection &
surfaces()
{
return _surfaces;
}
inline const SurfaceCollection &
surfaces() const
{
return _surfaces;
}
inline VolumeCollection &
volumes()
{
return _volumes;
}
inline const VolumeCollection &
volumes() const
{
return _volumes;
}
bool
hasPoints() const;
bool
hasSegments() const;
bool
hasSurfaces() const;
bool
hasVolumes() const;
std::unique_ptr<Geometry>
recompose() const;
void
filterCovered(GeometrySet<Dim> &output) const;
private:
void
_decompose(const Geometry &g);
PointCollection _points;
SegmentCollection _segments;
SurfaceCollection _surfaces;
VolumeCollection _volumes;
};
SFCGAL_API std::ostream &
operator<<(std::ostream &, const GeometrySet<2> &g);
SFCGAL_API std::ostream &
operator<<(std::ostream &, const GeometrySet<3> &g);
// bbox of a 'volume' for 2D, will never be called
inline CGAL::Bbox_2
compute_solid_bbox(const NoVolume &, dim_t<2>)
{
return CGAL::Bbox_2();
}
inline CGAL::Bbox_3
compute_solid_bbox(const TypeForDimension<3>::Volume &vol, dim_t<3>)
{
BOOST_ASSERT(vol.size_of_vertices());
MarkedPolyhedron::Point_const_iterator pit = vol.points_begin();
CGAL::Bbox_3 ret(pit->bbox());
++pit;
for (; pit != vol.points_end(); ++pit) {
ret = ret + pit->bbox();
}
return ret;
}
} // namespace detail
} // namespace SFCGAL
#endif