| 2156 | } |
| 2157 | |
| 2158 | Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std::vector<Expression*> &args) |
| 2159 | { |
| 2160 | using std::numbers::pi; |
| 2161 | |
| 2162 | if(!expr || !expr->getOwner()) |
| 2163 | _EXPR_THROW("Invalid owner.", expr); |
| 2164 | |
| 2165 | // Handle aggregate functions |
| 2166 | if (f > AGGREGATES) |
| 2167 | return evalAggregate(expr, f, args); |
| 2168 | |
| 2169 | switch (f) { |
| 2170 | case LIST: { |
| 2171 | if (args.size() == 1 && args[0]->isDerivedFrom<RangeExpression>()) |
| 2172 | return args[0]->getPyValue(); |
| 2173 | Py::List list(args.size()); |
| 2174 | int i = 0; |
| 2175 | for (auto &arg : args) |
| 2176 | list.setItem(i++, arg->getPyValue()); |
| 2177 | return list; |
| 2178 | } |
| 2179 | case TUPLE: { |
| 2180 | if (args.size() == 1 && args[0]->isDerivedFrom<RangeExpression>()) |
| 2181 | return Py::Tuple(args[0]->getPyValue()); |
| 2182 | Py::Tuple tuple(args.size()); |
| 2183 | int i = 0; |
| 2184 | for (auto &arg : args) |
| 2185 | tuple.setItem(i++, arg->getPyValue()); |
| 2186 | return tuple; |
| 2187 | } |
| 2188 | } |
| 2189 | |
| 2190 | if(args.empty()) |
| 2191 | _EXPR_THROW("Function requires at least one argument.",expr); |
| 2192 | |
| 2193 | switch (f) { |
| 2194 | case MINVERT: { |
| 2195 | Py::Object pyobj = args[0]->getPyValue(); |
| 2196 | if (PyObject_TypeCheck(pyobj.ptr(), &Base::MatrixPy::Type)) { |
| 2197 | auto m = static_cast<Base::MatrixPy*>(pyobj.ptr())->value(); |
| 2198 | if (fabs(m.determinant()) <= std::numeric_limits<double>::epsilon()) |
| 2199 | _EXPR_THROW("Cannot invert singular matrix.", expr); |
| 2200 | m.inverseGauss(); |
| 2201 | return Py::asObject(new Base::MatrixPy(m)); |
| 2202 | } else if (PyObject_TypeCheck(pyobj.ptr(), &Base::PlacementPy::Type)) { |
| 2203 | const auto &pla = *static_cast<Base::PlacementPy*>(pyobj.ptr())->getPlacementPtr(); |
| 2204 | return Py::asObject(new Base::PlacementPy(pla.inverse())); |
| 2205 | } else if (PyObject_TypeCheck(pyobj.ptr(), &Base::RotationPy::Type)) { |
| 2206 | const auto &rot = *static_cast<Base::RotationPy*>(pyobj.ptr())->getRotationPtr(); |
| 2207 | return Py::asObject(new Base::RotationPy(rot.inverse())); |
| 2208 | } |
| 2209 | _EXPR_THROW( |
| 2210 | "Function requires the first argument to be either Matrix, Placement or Rotation.", |
| 2211 | expr); |
| 2212 | break; |
| 2213 | } |
| 2214 | case MROTATE: { |
| 2215 | Py::Object rotationObject = args[1]->getPyValue(); |
nothing calls this directly
no test coverage detected