1 /* Copyright (c) 1997-2021
2    Ewgenij Gawrilow, Michael Joswig, and the polymake team
3    Technische Universität Berlin, Germany
4    https://polymake.org
5 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version: http://www.gnu.org/licenses/gpl.txt.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 --------------------------------------------------------------------------------
16 */
17 
18 #include "polymake/client.h"
19 #include "polymake/Set.h"
20 #include "polymake/Matrix.h"
21 #include "polymake/IncidenceMatrix.h"
22 #include "polymake/Graph.h"
23 
24 namespace polymake { namespace polytope  {
25 
26 template <typename Scalar>
normal_cone_impl(BigObject p,const Set<Int> & F,const std::string & ftv_section,const std::string & rays_section,const std::string & facets_section,OptionSet options)27 BigObject normal_cone_impl(BigObject p,
28                            const Set<Int>& F,
29                            const std::string& ftv_section,
30                            const std::string& rays_section,
31                            const std::string& facets_section,
32                            OptionSet options)
33 {
34    if (p.isa("Polytope")) {
35       const Set<Int> far_face = p.give("FAR_FACE");
36       if (incl(F, far_face) <= 0)
37          throw std::runtime_error("normal_cone: face is contained in the far face");
38    }
39    const bool
40       outer  = options["outer"],
41       attach = options["attach"];
42 
43    const IncidenceMatrix<> ftv = p.give(ftv_section);
44    const Matrix<Scalar> facet_normals = p.give(facets_section);
45    Matrix<Scalar> cone_normals(facet_normals.minor(accumulate(rows(ftv.minor(F,All)), operations::mul()), range_from(1)));
46    if (outer) cone_normals = -cone_normals;
47 
48    BigObject c("Cone", mlist<Scalar>());
49    const Matrix<Scalar> ls = p.give("LINEAR_SPAN");
50    if (attach) {
51       const Matrix<Scalar> rays = p.give(rays_section);
52       c.take("INPUT_RAYS") << rays.minor(F,All) / ( zero_vector<Scalar>() | cone_normals );
53       c.take("INPUT_LINEALITY") << ls;
54       c.take("CONE_AMBIENT_DIM") << cone_normals.cols()+1;
55    } else {
56       c.take("INPUT_RAYS") << cone_normals;
57       c.take("INPUT_LINEALITY") << ls.minor(All, range_from(1));
58       c.take("CONE_AMBIENT_DIM") << cone_normals.cols();
59    }
60    return c;
61 }
62 
63 template <typename Scalar>
inner_cone_impl(BigObject p,const Set<Int> & F,OptionSet options)64 BigObject inner_cone_impl(BigObject p,
65                              const Set<Int>& F,
66                              OptionSet options)
67 {
68    if (p.isa("Polytope")) {
69       const Set<Int> far_face = p.give("FAR_FACE");
70       if (incl(F, far_face) <= 0)
71          throw std::runtime_error("normal_cone: face is contained in the far face");
72    }
73    const bool
74       outer  = options["outer"],
75       attach = options["attach"];
76 
77    const Graph<> G = p.give("GRAPH.ADJACENCY");
78    const Matrix<Scalar> V = p.give("VERTICES");
79    std::vector<Vector<Scalar>> inner_rays_list;
80    for (Int v : F) {
81       for (Int w : G.out_adjacent_nodes(v) - F) {
82          if (outer) {
83             inner_rays_list.emplace_back(V[v] - V[w]);
84          } else {
85             inner_rays_list.emplace_back(V[w] - V[v]);
86          }
87       }
88    }
89    Matrix<Scalar> inner_rays(inner_rays_list.size(), V.cols(), entire(inner_rays_list));
90    inner_rays.col(0) = zero_vector<Scalar>(inner_rays.rows());
91 
92    BigObject c("Cone", mlist<Scalar>());
93    const Matrix<Scalar> ls = p.give("LINEAR_SPAN");
94    if (attach) {
95       const Matrix<Scalar> rays = p.give("RAYS");
96       c.take("INPUT_RAYS") << rays.minor(F,All) / inner_rays;
97       c.take("INPUT_LINEALITY") << ls;
98       c.take("CONE_AMBIENT_DIM") << V.cols();
99    } else {
100       c.take("INPUT_RAYS") << inner_rays.minor(All, range_from(1));
101       c.take("INPUT_LINEALITY") << ls.minor(All, range_from(1));
102       c.take("CONE_AMBIENT_DIM") << V.cols()-1;
103    }
104    return c;
105 }
106 
107 FunctionTemplate4perl("normal_cone_impl<Scalar>($$$$$$)");
108 
109 FunctionTemplate4perl("inner_cone_impl<Scalar>($$$)");
110 
111 } }
112 
113 // Local Variables:
114 // mode:C++
115 // c-basic-offset:3
116 // indent-tabs-mode:nil
117 // End:
118