Unverified Commit cf5feb8d authored by Joseph Mirabel's avatar Joseph Mirabel Committed by GitHub
Browse files

Merge pull request #145 from jmirabel/devel

[Python] Doc and minor update + [C++] bugfix
parents d7a7bd3f c5acdbcb
......@@ -48,6 +48,7 @@ ENDIF()
# Do not support CMake older than 2.8.12
CMAKE_POLICY(SET CMP0022 NEW)
SET(PROJECT_USE_KEYWORD_LINK_LIBRARIES TRUE)
SET(DOXYGEN_USE_TEMPLATE_CSS TRUE)
# Check if the submodule cmake have been initialized
IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/base.cmake")
......
FILE_PATTERNS = *.h *.hh *.hxx
GENERATE_XML = YES
EXPAND_ONLY_PREDEF = NO
......@@ -16,25 +16,81 @@ namespace visitor
template <typename function_type>
struct member_func_impl : boost::python::def_visitor<member_func_impl<function_type> >
{
member_func_impl(const char* n, function_type f) : name(n), function(f) {}
member_func_impl(const char* n, const function_type& f) : name(n), function(f) {}
template <class classT>
inline void visit(classT& c) const
{
c.def(name, function, doxygen::member_func_doc(function));
// Either a boost::python::keyword<N> object or a void_ object
call (c, member_func_args(function));
}
template <class classT, std::size_t nkeywords>
inline void call(classT& c, const boost::python::detail::keywords<nkeywords>& args) const
{
c.def(name, function, member_func_doc(function), args);
}
template <class classT>
inline void call(classT& c, const void_&) const
{
c.def(name, function, member_func_doc(function));
}
const char* name;
function_type function;
const function_type& function;
};
// TODO surprisingly, this does not work when defined here but it works when
// defined after the generated files are included.
template <typename function_type>
inline member_func_impl<function_type> member_func (const char* name, function_type function)
inline member_func_impl<function_type> member_func (const char* name, const function_type& function)
{
return member_func_impl<function_type>(name, function);
}
#define DOXYGEN_DOC_DECLARE_INIT_VISITOR(z,nargs,unused) \
template < \
typename Class \
BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, class Arg)> \
struct init_##nargs##_impl : boost::python::def_visitor<init_##nargs##_impl< \
Class \
BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, Arg)> > { \
typedef constructor_##nargs##_impl<Class BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, Arg)> constructor; \
typedef boost::python::init<BOOST_PP_ENUM_PARAMS(nargs, Arg)> init_base; \
\
template <class classT> \
inline void visit(classT& c) const { call (c, constructor::args()); } \
\
template <class classT> \
void call(classT& c, const boost::python::detail::keywords<nargs+1>& args) \
const \
{ \
c.def(init_base(constructor::doc(), args)); \
} \
\
template <class classT> \
void call(classT& c, const void_&) const \
{ \
c.def(init_base(constructor::doc())); \
} \
}; \
\
template <typename Class BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, class Arg)> \
inline init_##nargs##_impl<Class BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, Arg)> init () \
{ \
return init_##nargs##_impl<Class BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, Arg)>(); \
}
BOOST_PP_REPEAT(DOXYGEN_DOC_MAX_NUMBER_OF_ARGUMENTS_IN_CONSTRUCTOR, DOXYGEN_DOC_DECLARE_INIT_VISITOR, ~)
#undef DOXYGEN_DOC_DECLARE_INIT_VISITOR
} // namespace visitor
template<typename Func>
......
......@@ -4,12 +4,16 @@
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/mpl/void.hpp>
#ifndef DOXYGEN_DOC_MAX_NUMBER_OF_ARGUMENTS_IN_CONSTRUCTOR
#define DOXYGEN_DOC_MAX_NUMBER_OF_ARGUMENTS_IN_CONSTRUCTOR 10
#endif
namespace doxygen
{
typedef boost::mpl::void_ void_;
template <typename _class>
struct class_doc_impl
{
......@@ -41,16 +45,26 @@ inline const char* member_func_doc (FuncPtr)
return "";
}
template <typename FuncPtr>
inline void_ member_func_args (FuncPtr)
{
return void_();
}
#define DOXYGEN_DOC_DECLARE_CONSTRUCTOR(z,nargs,unused) \
template < \
typename Class \
BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, class Arg)> \
struct constructor_doc_##nargs##_impl { \
static inline const char* run () \
struct constructor_##nargs##_impl { \
static inline const char* doc () \
{ \
return ""; \
} \
static inline void_ args () \
{ \
return void_(); \
} \
}; \
\
template < \
......@@ -59,14 +73,14 @@ template < \
BOOST_PP_ENUM_PARAMS(nargs, class Arg)> \
inline const char* constructor_doc () \
{ \
return constructor_doc_##nargs##_impl< \
return constructor_##nargs##_impl< \
Class \
BOOST_PP_COMMA_IF(nargs) \
BOOST_PP_ENUM_PARAMS(nargs, Arg)>::run(); \
BOOST_PP_ENUM_PARAMS(nargs, Arg)>::doc(); \
}
BOOST_PP_REPEAT(DOXYGEN_DOC_MAX_NUMBER_OF_ARGUMENTS_IN_CONSTRUCTOR, DOXYGEN_DOC_DECLARE_CONSTRUCTOR, ~)
#undef DOXYGEN_DOC_DECLARE_CONSTRUCTOR
/*
template <typename Class>
inline const char* constructor_doc ()
......
......@@ -39,12 +39,16 @@ template_class_attribute_body = \
template_constructor_doc = \
"""
template <{tplargs}>
struct constructor_doc_{nargs}_impl< {classname_prefix}{comma}{argsstring} >
struct constructor_{nargs}_impl< {classname_prefix}{comma}{argsstring} >
{{
static inline const char* run ()
static inline const char* doc ()
{{
return "{docstring}";
}}
static inline boost::python::detail::keywords<{nargs}+1> args ()
{{
return ({argnamesstring});
}}
}};"""
template_destructor_doc = \
"""
......@@ -66,6 +70,16 @@ template_member_func_doc_body = \
"""
if (function_ptr == static_cast<{rettype} ({classname_prefix}*) {argsstring}>(&{classname_prefix}{membername}))
return "{docstring}";"""
template_member_func_args = \
"""
{template}inline boost::python::detail::keywords<{n}> member_func_args ({rettype} ({classname_prefix}*function_ptr) {argsstring})
{{{body}
return ({default_args});
}}"""
template_member_func_args_body = \
"""
if (function_ptr == static_cast<{rettype} ({classname_prefix}*) {argsstring}>(&{classname_prefix}{membername}))
return ({args});"""
template_static_func_doc = \
"""
{template}inline const char* member_func_doc ({rettype} (*function_ptr) {argsstring})
......@@ -177,7 +191,7 @@ class MemberDef(Reference):
self.const = (memberdefxml.attrib['const']=="yes")
self.static = (memberdefxml.attrib['static']=="yes")
self.rettype = memberdefxml.find('type')
self.params = tuple( [ (param.find('type'), param.find('array')) for param in self.xml.findall("param") ] )
self.params = tuple( [ (param.find('type'), param.find('declname'), param.find('array')) for param in self.xml.findall("param") ] )
self.special = self.rettype.text is None and len(self.rettype.getchildren())==0
#assert self.special or len(self.rettype.text) > 0
......@@ -208,9 +222,9 @@ class MemberDef(Reference):
if len(self.parent.template_params) > 0:
tplargs = " <" + ", ".join([ d['name'] for d in self.parent.template_params ]) + " > "
args = ", ".join(
[ self.xmlToType(type, array, parentClass=self.parent, tplargs=tplargs) for type,array in self.params])
[ self.xmlToType(type, array, parentClass=self.parent, tplargs=tplargs) for type,declname,array in self.params])
else:
args = ", ".join([ self.xmlToType(type, array) for type, array in self.params])
args = ", ".join([ self.xmlToType(type, array) for type,declname,array in self.params])
return args
def s_tpldecl (self):
......@@ -218,7 +232,7 @@ class MemberDef(Reference):
return ", ".join([ d['type'] + " " + d['name'] for d in self.template_params ])
def s_rettype (self):
assert not self.special
assert not self.special, "Member {} ({}) is a special function and no return type".format(self.name, self.id)
return self.xmlToType(self.rettype)
def s_name (self):
......@@ -230,6 +244,18 @@ class MemberDef(Reference):
self.xml.find('detaileddescription'),
self.index.output)
def n_args (self):
return len(self.params)
def s_argnamesstring (self):
def getdeclname(i,declname):
if declname is None or declname.text is None or declname.text.strip() == "":
return "arg{}".format(i)
return declname.text.strip()
arg = """boost::python::arg("{}")"""
argnames = ["self", ] + [ getdeclname(i, declname) for i,(_,declname,_) in enumerate(self.params)]
return ", ".join([ arg.format(n) for n in argnames ])
def include (self):
import os.path
loc = self.xml.find('location')
......@@ -411,7 +437,8 @@ class ClassCompound (CompoundBase):
for member in self.special_funcs:
docstring = member.s_docstring()
if len(docstring) == 0: continue
argnamesstring = member.s_argnamesstring()
if len(docstring) == 0 and len(argnamesstring) == 0: continue
if member.s_name()[0] == '~':
output.out (template_destructor_doc.format (
tplargs = self._templateDecl(),
......@@ -426,19 +453,24 @@ class ClassCompound (CompoundBase):
classname_prefix = self._className(),
argsstring = member.s_args(),
docstring = docstring,
argnamesstring = argnamesstring,
))
for prototype, members in member_funcs.items():
# remove undocumented members
documented_members = []
docstrings = []
argnamesstrings = []
for member in members:
docstring = member.s_docstring()
if len(docstring) == 0: continue
argnamesstring = member.s_argnamesstring()
if len(docstring) == 0 and len(argnamesstring) == 0: continue
documented_members.append (member)
docstrings.append (docstring)
argnamesstrings.append (argnamesstring)
if len(documented_members) == 0: continue
# Write docstrings
body = "".join([
template_member_func_doc_body.format (
classname_prefix = classname_prefix,
......@@ -459,6 +491,32 @@ class ClassCompound (CompoundBase):
body = body
))
# Write argnamesstrings
body = "".join([
template_member_func_args_body.format (
classname_prefix = classname_prefix,
membername = member.s_name(),
args = argnamesstring,
rettype = member.s_rettype(),
argsstring = member.s_prototypeArgs(),
)
for member, argnamesstring in zip(documented_members,argnamesstrings) ])
n_args = member.n_args()
default_args = ", ".join(["""boost::python::arg("self")""", ] +
[ """boost::python::arg("arg{}")""".format(i) for i in range(n_args) ]
)
output.out (template_member_func_args.format (
template = "template <{}>\n".format (tplargs) if len(tplargs) > 0 else "",
rettype = member.s_rettype(),
n = n_args+1,
default_args = default_args,
classname_prefix = classname_prefix,
argsstring = member.s_prototypeArgs(),
body = body
))
output.out (template_close_namespace.format (namespace="doxygen"))
output.close()
......
......@@ -299,218 +299,110 @@ namespace fcl
mutable Vec3f cached_guess;
};
/// @brief Fast implementation for sphere-capsule collision
template<>
bool GJKSolver::shapeIntersect<Sphere, Capsule>(const Sphere& s1, const Transform3f& tf1,
const Capsule& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Capsule, Sphere>(const Capsule &s1, const Transform3f& tf1,
const Sphere &s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
/// @brief Fast implementation for sphere-sphere collision
template<>
bool GJKSolver::shapeIntersect<Sphere, Sphere>(const Sphere& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
/// @brief Fast implementation for box-box collision
template<>
bool GJKSolver::shapeIntersect<Box, Box>(const Box& s1, const Transform3f& tf1,
const Box& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Sphere, Halfspace>(const Sphere& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Sphere>(const Halfspace& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Box, Halfspace>(const Box& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Box>(const Halfspace& s1, const Transform3f& tf1,
const Box& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Capsule, Halfspace>(const Capsule& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Capsule>(const Halfspace& s1, const Transform3f& tf1,
const Capsule& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Cylinder, Halfspace>(const Cylinder& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Cylinder>(const Halfspace& s1, const Transform3f& tf1,
const Cylinder& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Cone, Halfspace>(const Cone& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Cone>(const Halfspace& s1, const Transform3f& tf1,
const Cone& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Halfspace>(const Halfspace& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Halfspace>(const Plane& s1, const Transform3f& tf1,
const Halfspace& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Halfspace, Plane>(const Halfspace& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Sphere, Plane>(const Sphere& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Sphere>(const Plane& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Box, Plane>(const Box& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Box>(const Plane& s1, const Transform3f& tf1,
const Box& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Capsule, Plane>(const Capsule& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Capsule>(const Plane& s1, const Transform3f& tf1,
const Capsule& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Cylinder, Plane>(const Cylinder& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Cylinder>(const Plane& s1, const Transform3f& tf1,
const Cylinder& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Cone, Plane>(const Cone& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Cone>(const Plane& s1, const Transform3f& tf1,
const Cone& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
template<>
bool GJKSolver::shapeIntersect<Plane, Plane>(const Plane& s1, const Transform3f& tf1,
const Plane& s2, const Transform3f& tf2,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const;
/// @brief Fast implementation for sphere-triangle collision
template<>
bool GJKSolver::shapeTriangleInteraction
(const Sphere& s, const Transform3f& tf1, const Vec3f& P1, const Vec3f& P2,
const Vec3f& P3, const Transform3f& tf2, FCL_REAL& distance,
Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
template<>
bool GJKSolver::shapeTriangleInteraction
(const Halfspace& s, const Transform3f& tf1, const Vec3f& P1, const Vec3f& P2,
const Vec3f& P3, const Transform3f& tf2, FCL_REAL& distance,
Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
template<>
bool GJKSolver::shapeTriangleInteraction
(const Plane& s, const Transform3f& tf1, const Vec3f& P1, const Vec3f& P2,
const Vec3f& P3, const Transform3f& tf2, FCL_REAL& distance,
Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
/// @brief Fast implementation for sphere-capsule distance
template<>
bool GJKSolver::shapeDistance<Sphere, Capsule>
(const Sphere& s1, const Transform3f& tf1,
const Capsule& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
template<>
bool GJKSolver::shapeDistance<Capsule, Sphere>
(const Capsule& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
/// @brief Fast implementation for sphere-cylinder distance
template<>
bool GJKSolver::shapeDistance<Sphere, Cylinder>
(const Sphere& s1, const Transform3f& tf1,
const Cylinder& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
template<>
bool GJKSolver::shapeDistance<Cylinder, Sphere>
(const Cylinder& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
/// @brief Fast implementation for sphere-sphere distance
template<>
bool GJKSolver::shapeDistance<Sphere, Sphere>
(const Sphere& s1, const Transform3f& tf1,
const Sphere& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
// @brief Computation of the distance result for capsule capsule. Closest points are based on two line-segments.
template<>
bool GJKSolver::shapeDistance<Capsule, Capsule>
(const Capsule& s1, const Transform3f& tf1,
const Capsule& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
// Distance computation between two triangles
//
// Do not run EPA algorithm to compute penetration depth, use a dedicated
// method.
template<>
bool GJKSolver::shapeDistance<TriangleP, TriangleP>
(const TriangleP& s1, const Transform3f& tf1,
const TriangleP& s2, const Transform3f& tf2,
FCL_REAL& dist, Vec3f& p1, Vec3f& p2, Vec3f& normal) const;
/// \name Shape intersection specializations
/// \{
// param doc is the doxygen detailled description (should be enclosed in /** */
// and contain no space.
#define HPP_FCL_DECLARE_SHAPE_INTERSECT(Shape1,Shape2,doc) \
/** @brief Fast implementation for Shape1-Shape2 collision. */ \
doc \
template<> \
bool GJKSolver::shapeIntersect<Shape1, Shape2> \
(const Shape1& s1, const Transform3f& tf1, \
const Shape2& s2, const Transform3f& tf2, \
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal) const
#define HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF(Shape,doc) \
HPP_FCL_DECLARE_SHAPE_INTERSECT(Shape,Shape,doc)
#define HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Shape1,Shape2,doc) \
HPP_FCL_DECLARE_SHAPE_INTERSECT(Shape1,Shape2,doc); \
HPP_FCL_DECLARE_SHAPE_INTERSECT(Shape2,Shape1,doc)
HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF(Sphere,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Sphere, Capsule,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Sphere, Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Sphere, Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF(Box,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Box, Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Box, Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Capsule, Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Capsule, Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Cylinder, Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Cylinder, Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Cone, Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Cone, Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF(Halfspace,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF(Plane,);
HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR(Plane, Halfspace,);
#undef HPP_FCL_DECLARE_SHAPE_INTERSECT
#undef HPP_FCL_DECLARE_SHAPE_INTERSECT_SELF
#undef HPP_FCL_DECLARE_SHAPE_INTERSECT_PAIR
/// \}
/// \name Shape triangle interaction specializations
/// \{
#define HPP_FCL_DECLARE_SHAPE_TRIANGLE(Shape,doc) \
/** @brief Fast implementation for Shape-Triangle interaction. */ \
doc \
template<> bool GJKSolver::shapeTriangleInteraction<Shape> \
(const Shape& s, const Transform3f& tf1, const Vec3f& P1, const Vec3f& P2, \
const Vec3f& P3, const Transform3f& tf2, FCL_REAL& distance, \
Vec3f& p1, Vec3f& p2, Vec3f& normal) const