1 #ifndef VIGRA_POLYTOPE_HXX
2 #define VIGRA_POLYTOPE_HXX
5 #error "Should only be included with flag \"WITH_LEMON\""
9 #include <lemon/list_graph.h>
10 #include <lemon/maps.h>
14 #include "tinyvector.hxx"
15 #include "array_vector.hxx"
16 #include "linear_algebra.hxx"
17 #include "numerictraits.hxx"
18 #include "permutation.hxx"
27 template <
unsigned int N,
class T>
32 enum Dimension {dimension = N};
33 enum node_enum {INVALID, FACET, VERTEX};
35 template <node_enum NodeType>
36 struct node_type_iterator;
38 typedef T coordinate_type;
39 typedef typename NumericTraits<T>::RealPromote real_type;
42 typedef typename point_type::difference_type difference_type;
43 typedef typename lemon::ListDigraph graph_type;
44 typedef typename graph_type::Node node_type;
45 typedef typename graph_type::Arc arc_type;
46 typedef typename graph_type::NodeIt node_iterator;
47 typedef typename graph_type::OutArcIt out_arc_iterator;
48 typedef typename graph_type::InArcIt in_arc_iterator;
49 typedef node_type_iterator<FACET> facet_iterator;
50 typedef node_type_iterator<VERTEX> vertex_iterator;
76 lemon::digraphCopy(other.graph_, graph_);
77 lemon::mapCopy(other.graph_, other.type_map_, type_map_);
78 lemon::mapCopy(other.graph_, other.vec_map_, vec_map_);
79 lemon::mapCopy(other.graph_, other.aligns_map_, aligns_map_);
82 virtual bool contains(
const point_view_type & p)
const = 0;
84 virtual real_type nVolume()
const = 0;
86 virtual real_type nSurface()
const = 0;
90 virtual bool closed(
const node_type n)
const
93 type_map_[n] == FACET,
94 "Polytope::closed(): Node needs do be a facet");
96 aligns_map_[n].begin(),
98 lemon::INVALID) == aligns_map_[n].end();
105 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
120 node_type ret = graph_.addNode();
121 type_map_[ret] = VERTEX;
123 for (
int i = 0; i < N; i++)
125 aligns_map_[ret][i] = lemon::INVALID;
135 type_map_[u] == FACET,
136 "Polytope::eraseFacet(): Node needs to be a facet");
137 for (
auto neighbor : aligns_map_[u])
139 if (neighbor != lemon::INVALID)
142 aligns_map_[neighbor].begin(),
143 aligns_map_[neighbor].end(),
146 it != aligns_map_[neighbor].end(),
147 "Polytope::eraseFacet(): Inconsistent aligns map");
148 *it = lemon::INVALID;
161 std::set<node_type> ret;
162 if (type_map_[u] == FACET)
164 for (out_arc_iterator a(graph_, u); a != lemon::INVALID; ++a)
166 ret.insert(graph_.target(a));
171 for (in_arc_iterator a(graph_, u); a != lemon::INVALID; ++a)
173 ret.insert(graph_.source(a));
183 type_map_[u] == FACET,
184 "Polytope::getVertices(): Node must be a facet");
186 for (out_arc_iterator a(graph_, u); a != lemon::INVALID; ++a)
188 ret.push_back(vec_map_[graph_.target(a)]);
199 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
213 std::set<node_type> to_erase;
214 for (vertex_iterator v(graph_, type_map_); v != lemon::INVALID; ++v)
217 type_map_[v] == VERTEX,
218 "Polytope::tidyUp(): vertex not a vertex");
219 in_arc_iterator a(graph_, v);
220 if (a == lemon::INVALID)
225 for (node_type v : to_erase)
235 type_map_[u] == FACET,
236 "Polytope::distance(): Node must be a facet");
237 out_arc_iterator a(graph_, u);
240 "Polytope::distance(): Invalid facet");
242 return dot(p - vec_map_[graph_.target(a)], vec_map_[u]);
249 const unsigned int label,
255 unsigned int ret = 0;
256 typename array_type::iterator it = array.
begin();
257 for (it = array.
begin(); it != array.
end(); it++)
259 const typename array_type::difference_type coord = it.template get<0>();
261 for (
unsigned int i = 0; i < vec.size(); i++)
263 vec[i] = coord[i]*scale[i] + offset[i];
265 if (this->contains(vec))
278 const unsigned int label,
283 "Polytope::fill(): Polytope not closed.");
286 unsigned int ret = 0;
287 typename array_type::iterator it = array.
begin();
288 for (it = array.
begin(); it != array.
end(); it++)
290 const typename array_type::difference_type coord = it.template get<0>();
292 for (
unsigned int i = 0; i < vec.size(); i++)
294 vec[i] = coord[i] + offset[i];
296 if (this->contains(vec))
307 virtual bool isConnected(
308 const node_type vertex,
309 const node_type facet)
const
312 type_map_[vertex] == VERTEX,
313 "Polytope::isConnected(): First node must be a vertex");
315 type_map_[facet] == FACET,
316 "Polytope::isConnected(): Second node must be a facet");
317 for (out_arc_iterator a(graph_, facet); a != lemon::INVALID; ++a)
319 if (graph_.target(a) == vertex)
327 virtual node_type findNeighbor(
329 const difference_type index)
const
332 type_map_[u] == FACET,
333 "Polytope::findNeighbor(): Node must be a facet");
336 "Polytope::findNeighbor(): Invalid index");
338 countOutArcs(graph_, u) == dimension,
339 "Polytope::findNeighbor(): Bad facet");
340 out_skip_iterator a(graph_, u, index);
341 const node_type first_vertex = graph_.target(a);
346 out_skip_iterator b(a);
350 if (b == lemon::INVALID)
354 }
while (isConnected(graph_.target(b), candidate));
357 return lemon::INVALID;
360 void assignNeighbors(
const node_type u)
363 type_map_[u] == FACET,
364 "Polytope::assignNeighbors(): Node must be facet");
365 for (
int i = 0; i < dimension; i++)
367 aligns_map_[u][i] = this->findNeighbor(u, i);
371 void updateInvalidNeighbors(
const node_type u)
374 type_map_[u] == FACET,
375 "Polytope::assignNeighbors(): Node must be facet");
376 for (
int i = 0; i < dimension; i++)
378 if (aligns_map_[u][i] == lemon::INVALID)
380 aligns_map_[u][i] = this->findNeighbor(u, i);
385 ArrayVector<node_type> openEdge(
const node_type u)
388 type_map_[u] == FACET,
389 "Polytope::openEdge(): Node must be facet");
391 lemon::countOutArcs(graph_, u) == dimension,
392 "Polytope::openEdge(): Got invalid facet");
393 ArrayVector<node_type> ret;
394 for (
int i = 0; i < dimension; i++)
396 if (aligns_map_[u][i] == lemon::INVALID)
398 for (out_skip_iterator a(graph_, u, i); a != lemon::INVALID; ++a)
400 ret.push_back(graph_.target(a));
410 template <node_enum NodeType>
411 struct node_type_iterator :
public node_type
416 explicit node_type_iterator(
417 const graph_type & graph,
418 const typename graph_type::NodeMap<node_enum> & type_map)
420 , type_map_(type_map)
422 graph_.first(static_cast<node_type &>(*
this));
423 while (*
this != lemon::INVALID && type_map_[*
this] != NodeType)
429 node_type_iterator<NodeType> & operator++()
431 while (*
this != lemon::INVALID)
434 if (type_map_[*
this] == NodeType)
444 return (static_cast<node_type>(*
this) == i);
449 return (static_cast<node_type>(*
this) != i);
452 const graph_type & graph_;
453 const typename graph_type::NodeMap<node_enum> & type_map_;
456 struct out_skip_iterator :
public arc_type
461 explicit out_skip_iterator(
462 const graph_type & graph,
463 const node_type & node,
464 const difference_type skip)
469 graph_.firstOut(*
this, node);
472 graph_.nextOut(*
this);
476 out_skip_iterator & operator++()
479 graph_.nextOut(*
this);
482 graph_.nextOut(*
this);
489 return (static_cast<arc_type>(*
this) == i);
494 return (static_cast<arc_type>(*
this) != i);
497 difference_type index()
const
502 const graph_type & graph_;
503 const difference_type skip_;
504 difference_type index_;
508 typename graph_type::NodeMap<node_enum> type_map_;
509 typename graph_type::NodeMap<point_type> vec_map_;
510 typename graph_type::NodeMap<TinyVector<node_type, N> > aligns_map_;
516 template <
unsigned int N,
class T>
522 typedef typename base_type::coordinate_type coordinate_type;
523 typedef typename base_type::real_type real_type;
526 typedef typename base_type::difference_type difference_type;
527 typedef typename base_type::graph_type graph_type;
528 typedef typename base_type::node_type node_type;
529 typedef typename base_type::arc_type arc_type;
530 typedef typename base_type::node_iterator node_iterator;
531 typedef typename base_type::in_arc_iterator in_arc_iterator;
532 typedef typename base_type::out_arc_iterator out_arc_iterator;
533 typedef typename base_type::out_skip_iterator out_skip_iterator;
534 typedef typename base_type::facet_iterator facet_iterator;
535 typedef typename base_type::vertex_iterator vertex_iterator;
537 using base_type::dimension;
538 using base_type::graph_;
539 using base_type::vec_map_;
540 using base_type::type_map_;
541 using base_type::aligns_map_;
542 using base_type::INVALID;
543 using base_type::FACET;
544 using base_type::VERTEX;
575 "StarPolytope::StarPolytope(): Signature only for use in 2D");
598 "StarPolytope::StarPolytope(): Signature only for use in 3D");
616 virtual void assignNormal(
const node_type & u)
619 type_map_[u] == FACET,
620 "StarPolytope::assignNormal(): Node needs to be a facet node");
622 out_arc_iterator a(graph_, u);
623 point_view_type vertex = vec_map_[graph_.target(a)];
625 for (
int i = 0; a != lemon::INVALID; ++a, ++i)
627 const point_type vec = vec_map_[graph_.target(a)] - vertex;
628 std::copy(vec.begin(), vec.end(),
rowVector(mat, i).begin());
630 point_view_type normal = vec_map_[u];
631 for (
int i = 0; i < dimension; i++)
635 for (
auto permutation : permutations_)
637 coordinate_type val = 1;
638 for (
int i = 0; i < dimension - 1; i++)
640 val *= mat(i, permutation[i]);
642 val *= permutation.sign();
643 normal[permutation[dimension - 1]] += val;
645 if (
dot(normal, vertex - center_) < 0)
653 virtual node_type
addFacet(
const node_type & a,
const node_type & b)
657 "StarPolytope::addFacet(): Signature only for use in 2D");
658 node_type ret = graph_.addNode();
659 type_map_[ret] = FACET;
660 graph_.addArc(ret, a);
661 graph_.addArc(ret, b);
663 lemon::countOutArcs(graph_, ret) == dimension,
664 "StarPolytope::addFacet(): Invalid facet created");
665 this->assignNormal(ret);
666 this->assignNeighbors(ret);
667 for (
auto facet : aligns_map_[ret])
669 if (facet != lemon::INVALID)
672 type_map_[facet] == FACET,
673 "StarPolytope::addFacet(): Node must be facet");
674 this->updateInvalidNeighbors(facet);
689 "StarPolytope::addFacet(): Signature only for use in 3D");
690 node_type ret = graph_.addNode();
691 type_map_[ret] = FACET;
692 graph_.addArc(ret, a);
693 graph_.addArc(ret, b);
694 graph_.addArc(ret, c);
696 lemon::countOutArcs(graph_, ret) == dimension,
697 "StarPolytope::addFacet(): Invalid facet created");
698 this->assignNormal(ret);
699 this->assignNeighbors(ret);
700 for (
auto facet : aligns_map_[ret])
702 if (facet != lemon::INVALID)
705 type_map_[facet] == FACET,
706 "StarPolytope::addFacet(): Node must be facet");
707 this->updateInvalidNeighbors(facet);
716 lemon::countNodes(graph_) == dimension + 1,
717 "StarPolytope::close(): Can only close for dim+1 vertices");
720 vertex_iterator v(graph_, type_map_);
721 center_ = vec_map_[v];
722 for (++v; v != lemon::INVALID; ++v)
724 center_ += vec_map_[v];
726 center_ /=
static_cast<real_type
>(dimension + 1);
729 for (
int i = 0; i < dimension + 1; i++)
731 node_type facet = graph_.addNode();
732 type_map_[facet] = FACET;
733 vertex_iterator v(graph_, type_map_);
734 for (
int j = 0; j < dimension; ++j, ++v)
740 graph_.addArc(facet, v);
743 lemon::countOutArcs(graph_, facet) == dimension,
744 "StarPolytope::close(): Invalid facet created");
745 this->assignNormal(facet);
746 this->assignNeighbors(facet);
747 for (
auto neighbor : aligns_map_[facet])
749 if (neighbor != lemon::INVALID)
752 type_map_[neighbor] == FACET,
753 "StarPolytope::close(): Node must be facet");
754 this->updateInvalidNeighbors(neighbor);
760 virtual bool contains(
const node_type & n,
const point_view_type & p)
const
763 type_map_[n] == FACET,
764 "StarPolytope::contains(): Node needs do be a facet");
765 ArrayVector<point_view_type>
vertices = this->getVertices(n);
766 vertices.push_back(center_);
767 MultiArray<2, coordinate_type> jp_mat(dimension, dimension);
768 MultiArray<2, coordinate_type> jj_mat(dimension, dimension);
769 for (
int j = 0; j < dimension + 1; j++)
771 for (
int i = 0, ii = 0; i < dimension; i++, ii++)
778 const point_type vec = vertices[ii] - p;
779 std::copy(vec.begin(), vec.end(),
rowVector(jp_mat, i).begin());
782 const point_type vec = vertices[ii] - vertices[j];
783 std::copy(vec.begin(), vec.end(),
rowVector(jj_mat, i).begin());
788 const coordinate_type eps = std::numeric_limits<T>::epsilon() * 2;
789 if (((jj_det > 0) != (jp_det > 0)) &&
abs(jp_det) > eps)
801 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
811 virtual real_type
nVolume(
const node_type & n)
const
814 type_map_[n] == FACET,
815 "StarPolytope::nVolume(): Node needs do be a facet");
818 out_arc_iterator a(graph_, n);
819 for (
int i = 0; i < dimension; ++i, ++a)
822 const point_type vec = vec_map_[graph_.target(a)] - center_;
823 std::copy(vec.begin(), vec.end(),
rowVector(mat, i).begin());
833 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
840 virtual real_type
nSurface(
const node_type & n)
const
843 type_map_[n] == FACET,
844 "StarPolytope::nVolume(): Node needs do be a facet");
846 real_type factor = vec_map_[n].magnitude();
847 out_arc_iterator a(graph_, n);
848 const point_view_type vec = vec_map_[graph_.target(a)];
850 for (
int i = 1; i < dimension; ++i, ++a)
853 const point_type tmp = vec_map_[graph_.target(a)] - vec;
854 std::copy(tmp.begin(), tmp.end(),
rowVector(mat, i).begin());
856 const point_type tmp = vec_map_[n];
857 std::copy(tmp.begin(), tmp.end(),
rowVector(mat, 0).begin());
866 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
875 PlainChangesPermutations<N> permutations_;
881 template <
unsigned int N,
class T>
887 typedef typename base_type::coordinate_type coordinate_type;
888 typedef typename base_type::real_type real_type;
891 typedef typename base_type::difference_type difference_type;
892 typedef typename base_type::graph_type graph_type;
893 typedef typename base_type::node_type node_type;
894 typedef typename base_type::arc_type arc_type;
895 typedef typename base_type::node_iterator node_iterator;
896 typedef typename base_type::in_arc_iterator in_arc_iterator;
897 typedef typename base_type::out_arc_iterator out_arc_iterator;
898 typedef typename base_type::out_skip_iterator out_skip_iterator;
899 typedef typename base_type::facet_iterator facet_iterator;
900 typedef typename base_type::vertex_iterator vertex_iterator;
902 using base_type::dimension;
903 using base_type::graph_;
904 using base_type::vec_map_;
905 using base_type::type_map_;
906 using base_type::aligns_map_;
907 using base_type::INVALID;
908 using base_type::FACET;
909 using base_type::VERTEX;
933 :
base_type(a, b, c, d, (a + b + c + d) / 4)
938 virtual void closeFacet(
939 const node_type & vertex,
940 const node_type & facet)
943 type_map_[vertex] == VERTEX,
944 "ConvexPolytope::closeFacet(): Vertex needs to be a vertex node");
946 type_map_[facet] == FACET,
947 "ConvexPolytope::closeFacet(): Facet needs to be a facet node");
950 "ConvexPolytope::closeFacet(): Cannot close facet with vertex");
952 while (!(this->
closed(facet)))
956 vertices.
size() == (dimension - 1),
957 "StarPolytope::closeFacet(): Invalid facet");
958 node_type new_facet = graph_.addNode();
959 type_map_[new_facet] = FACET;
960 graph_.addArc(new_facet, vertex);
961 for (
auto n : vertices)
963 graph_.addArc(new_facet, n);
966 lemon::countOutArcs(graph_, new_facet) == dimension,
967 "ConvexPolytope::closeFacet(): Invalid facet created");
968 this->assignNormal(new_facet);
969 this->assignNeighbors(new_facet);
970 for (
auto neighbor : aligns_map_[new_facet])
972 if (neighbor != lemon::INVALID)
975 type_map_[facet] == FACET,
976 "StarPolytope::addFacet(): Node must be facet");
977 this->updateInvalidNeighbors(neighbor);
985 virtual bool contains(
const node_type & n,
const point_view_type & p)
const
988 type_map_[n] == FACET,
989 "ConvexPolytope::contains(): Node needs do be a facet");
990 const out_arc_iterator a(graph_, n);
993 const real_type scalar =
dot(p - vertex, normal);
994 return (scalar < std::numeric_limits<T>::epsilon() * 2);
999 for (facet_iterator n(graph_, type_map_); n != lemon::INVALID; ++n)
1001 if (!contains(n, p))
1016 "ConvexPolytope::addExtremeVertex(): Polytope needs to be closed");
1018 if (lit_facets.
size() > 0)
1020 std::set<node_type> open_facets;
1021 for (node_type lit_facet : lit_facets)
1023 for (
auto con : aligns_map_[lit_facet])
1025 if (con != lemon::INVALID)
1028 type_map_[con] == FACET,
1029 "ConvexPolytope::addExtremeVertex(): "
1030 "facet not a facet");
1031 open_facets.insert(con);
1034 open_facets.erase(lit_facet);
1038 node_type new_vertex = this->
addVertex(p);
1039 for (
auto open_facet : open_facets)
1041 this->closeFacet(new_vertex, open_facet);
iterator end()
Definition: multi_array.hxx:1937
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product
Definition: rgbvalue.hxx:906
virtual void eraseFacet(const node_type u)
Definition: polytope.hxx:132
virtual bool contains(const point_view_type &p) const
Definition: polytope.hxx:997
virtual unsigned int fill(MultiArrayView< N, unsigned int > &array, const unsigned int label, const point_view_type offset) const
Definition: polytope.hxx:276
virtual node_type addFacet(const node_type &a, const node_type &b, const node_type &c)
Definition: polytope.hxx:682
StarPolytope()
Definition: polytope.hxx:550
iterator begin()
Definition: multi_array.hxx:1921
Main MultiArray class containing the memory management.
Definition: multi_array.hxx:2474
virtual real_type nVolume() const
Definition: polytope.hxx:830
virtual std::set< node_type > getConnected(const node_type u) const
Definition: polytope.hxx:159
StarPolytope(const point_view_type &a, const point_view_type &b, const point_view_type &c, const point_view_type &d, const point_view_type ¢er)
Definition: polytope.hxx:587
Polytope(const Polytope< N, T > &other)
Definition: polytope.hxx:63
StarPolytope(const point_view_type ¢er)
Definition: polytope.hxx:557
Definition: array_vector.hxx:58
virtual ArrayVector< node_type > litFacets(const point_view_type &p) const
Definition: polytope.hxx:196
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
virtual real_type nSurface() const
Definition: polytope.hxx:863
std::pair< typename vigra::GridGraph< N, DirectedTag >::vertex_iterator, typename vigra::GridGraph< N, DirectedTag >::vertex_iterator > vertices(vigra::GridGraph< N, DirectedTag > const &g)
Get a (begin, end) iterator pair for the vertices of graph g (API: boost).
Definition: multi_gridgraph.hxx:2840
virtual real_type distance(const node_type u, const point_view_type &p) const
Definition: polytope.hxx:232
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
virtual void addExtremeVertex(const point_view_type &p)
Definition: polytope.hxx:1012
Represent an n-dimensional polytope.
Definition: polytope.hxx:28
Wrapper for fixed size vectors.
Definition: tinyvector.hxx:621
virtual unsigned int fill(MultiArrayView< N, unsigned int > &array, const unsigned int label, const point_view_type offset, const point_view_type scale) const
Definition: polytope.hxx:247
Polytope()
Definition: polytope.hxx:54
virtual bool closed(const node_type n) const
Definition: polytope.hxx:90
MultiArrayView< 2, T, C > rowVector(MultiArrayView< 2, T, C > const &m, MultiArrayIndex d)
Definition: matrix.hxx:697
Definition: polytope.hxx:882
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
virtual node_type addVertex(const point_view_type &p)
Definition: polytope.hxx:118
StarPolytope(const point_view_type &a, const point_view_type &b, const point_view_type &c, const point_view_type ¢er)
Definition: polytope.hxx:565
size_type size() const
Definition: array_vector.hxx:358
virtual void tidyUp()
Definition: polytope.hxx:211
virtual node_type addFacet(const node_type &a, const node_type &b)
Definition: polytope.hxx:653
virtual point_type getCenter() const
Definition: polytope.hxx:611
virtual bool contains(const point_view_type &p) const
Definition: polytope.hxx:799
Specialization of the polytope to polytopes which forms a star domain.
Definition: polytope.hxx:517
NumericTraits< T >::Promote determinant(MultiArrayView< 2, T, C1 > const &a, std::string method="default")
Definition: linear_solve.hxx:859
virtual void operator=(const Polytope< N, T > &other)
Definition: polytope.hxx:74
virtual bool closed() const
Definition: polytope.hxx:103