Commit 43c95fcf authored by Dennis Gläser's avatar Dennis Gläser
Browse files

Merge branch 'feature/python-intersections' into 'master'

Feature/python intersections

See merge request tools/frackit!147
parents 8bcf7185 80cd0bab
......@@ -54,6 +54,8 @@ intersect_segment_segment(const Segment<ctype, wd>& segment1,
const Segment<ctype, wd>& segment2,
ctype eps)
{
static_assert(wd == 3, "Segment-Segment algorithm currently only works in 3d");
using ResultType = Intersection<Segment<ctype, wd>, Segment<ctype, wd>>;
using Segment = Frackit::Segment<ctype, wd>;
using Direction = typename Segment::Direction;
......@@ -108,8 +110,7 @@ intersect_segment_segment(const Segment<ctype, wd>& segment1,
for (TopExp_Explorer explorer(edge, TopAbs_VERTEX); explorer.More(); explorer.Next())
{
auto curPoint = OCCUtilities::point(TopoDS::Vertex(explorer.Current()));
if (!curPoint.isEqual(s1, eps) && !curPoint.isEqual(t1, eps)
&& !curPoint.isEqual(s2, eps) && !curPoint.isEqual(t2, eps))
if (segment1.contains(curPoint, eps) && segment2.contains(curPoint, eps))
return ResultType( std::move(curPoint) );
}
}
......
......@@ -26,6 +26,7 @@
#include <string>
#include <variant>
#include <algorithm>
namespace Frackit {
......
add_subdirectory(common)
add_subdirectory(geometry)
add_subdirectory(intersection)
add_subdirectory(io)
add_subdirectory(magnitude)
add_subdirectory(occutilities)
......
install(FILES
emptyintersection.hh
intersect.hh
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/frackit/python/intersection)
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*****************************************************************************
* See the file COPYING for full copying permissions. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*****************************************************************************/
#ifndef FRACKIT_PYTHON_EMPTY_INTERSECTION_HH
#define FRACKIT_PYTHON_EMPTY_INTERSECTION_HH
#include <string>
#include <pybind11/pybind11.h>
#include <frackit/intersection/emptyintersection.hh>
#include <frackit/python/geometry/registerdimensionproperties.hh>
namespace Frackit::Python {
namespace py = pybind11;
namespace Detail {
template<class ct, int wd>
void registerEmptyIntersection(py::module& module)
{
using EI = Frackit::EmptyIntersection<wd, ct>;
const std::string className = "EmptyIntersection_" + std::to_string(wd);
py::class_<EI> cls(module, className.c_str());
cls.def("name", &EI::name, "return the name of this (empty) geometry");
registerDimensionProperties(cls);
}
} // end namespace Detail
template<class ctype>
void registerEmptyIntersection(py::module& module)
{
Detail::registerEmptyIntersection<ctype, 1>(module);
Detail::registerEmptyIntersection<ctype, 2>(module);
Detail::registerEmptyIntersection<ctype, 3>(module);
}
} // end namespace Frackit::Python
#endif
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*****************************************************************************
* See the file COPYING for full copying permissions. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*****************************************************************************/
#ifndef FRACKIT_PYTHON_INTERSECT_HH
#define FRACKIT_PYTHON_INTERSECT_HH
#include <vector>
#include <variant>
#include <type_traits>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <frackit/geometry/segment.hh>
#include <frackit/geometry/disk.hh>
#include <frackit/geometry/quadrilateral.hh>
#include <frackit/geometry/polygon.hh>
#include <frackit/geometry/cylindersurface.hh>
#include <frackit/python/occutilities/brepwrapper.hh>
#include <frackit/intersection/intersect.hh>
#include <frackit/intersection/intersectiontraits.hh>
namespace Frackit::Python {
namespace Detail {
//! for compatibility with BRepWrapper classes
template<class Geo> struct UnwrapperHelper { using type = Geo; };
template<class Geo> struct UnwrapperHelper<OCCUtilities::BRepWrapper<Geo>> { using type = Geo; };
template<class Geo> using UnwrappedType = typename UnwrapperHelper<Geo>::type;
//! the converted type of an individual geometry type
template<class Geo>
using ConvertedType = std::conditional_t< std::is_convertible_v<Geo, TopoDS_Shape>,
OCCUtilities::BRepWrapper<Geo>,
Geo >;
template<class T> struct IsVector : public std::false_type {};
template<class T> struct IsVector<std::vector<T>> : public std::true_type {};
template<class T> struct IntersectionVariant { using type = T; };
template<class T> struct IntersectionVariant<std::vector<T>> { using type = T; };
template<class T> struct ConvertedVariant;
template<class... Geoms>
struct ConvertedVariant<std::variant<Geoms...>>
{ using type = std::variant< ConvertedType<Geoms>... >; };
//! Convert an intersection result into new one using ShapeWrappers
template<class T>
using ConvertVariant = typename ConvertedVariant<T>::type;
//! Uses the converter to define the new intersection result
template<class T>
using ConvertIntersection = std::conditional_t< IsVector<T>::value,
std::vector<ConvertVariant<typename IntersectionVariant<T>::type>>,
ConvertVariant<typename IntersectionVariant<T>::type> >;
//! Alias for the converted intersection result type
template<class Intersection>
using ConvertedIntersection = ConvertIntersection<Intersection>;
//! Alias for the intersection result type between two geometries
template<class Geo1, class Geo2>
using IntersectionResult = ConvertedIntersection<Frackit::Intersection<UnwrappedType<Geo1>,
UnwrappedType<Geo2>>>;
//! convert shape into wrapper
template<class Geo, std::enable_if_t<std::is_convertible_v<Geo, TopoDS_Shape>, int> = 0>
OCCUtilities::BRepWrapper<Geo> convertShape(const Geo& geo) { return {geo}; }
template<class Geo, std::enable_if_t<!std::is_convertible_v<Geo, TopoDS_Shape>, int> = 0>
Geo convertShape(const Geo& geo) { return geo; }
//! parse the result of an intersection into the converted type
template<class Intersection, std::enable_if_t<!IsVector<Intersection>::value, int> = 0>
ConvertedIntersection<Intersection> convertIntersectionResult(const Intersection& is)
{
ConvertedIntersection<Intersection> result;
std::visit([&result] (const auto& geo) { result = convertShape(geo); }, is);
return result;
}
//! parse the result of an intersection (multiple geometries) into the converted type
template<class Intersection, std::enable_if_t<IsVector<Intersection>::value, int> = 0>
ConvertedIntersection<Intersection> convertIntersectionResult(const Intersection& is)
{
ConvertedIntersection<Intersection> result;
for (const auto& geo : is)
result.push_back(convertIntersectionResult(geo));
return result;
}
//! convert intersection result such that all TopoDS_Shape classes
//! are converted into the ShapeWrappers registered in the Python bindings
template<class Geo1, class Geo2>
IntersectionResult<Geo1, Geo2> intersectAndConvert(const Geo1& geo1, const Geo2& geo2)
{ return convertIntersectionResult(Frackit::intersect(geo1, geo2)); }
//! convert intersection result such that all TopoDS_Shape classes
//! are converted into the ShapeWrappers registered in the Python bindings
template<class Geo1, class Geo2, class ctype>
IntersectionResult<Geo1, Geo2> intersectAndConvert(const Geo1& geo1, const Geo2& geo2, ctype eps)
{ return convertIntersectionResult(Frackit::intersect(geo1, geo2, eps)); }
//! convert shape wrapper function arguments into shape representations and forward
template<class Geo1, class Geo2>
IntersectionResult<Geo1, Geo2> intersect(const Geo1& geo1, const Geo2& geo2)
{
constexpr bool isWrapper1 = OCCUtilities::IsBRepWrapper<Geo1>::value;
constexpr bool isWrapper2 = OCCUtilities::IsBRepWrapper<Geo2>::value;
if constexpr (isWrapper1 && isWrapper2)
return intersectAndConvert(geo1.get(), geo2.get());
else if constexpr(isWrapper1 && !isWrapper2)
return intersectAndConvert(geo1.get(), geo2);
else if constexpr(!isWrapper1 && isWrapper2)
return intersectAndConvert(geo1, geo2.get());
else
return intersectAndConvert(geo1, geo2);
}
//! convert shape wrapper function arguments into shape representations and forward
template<class Geo1, class Geo2, class ctype>
IntersectionResult<Geo1, Geo2> intersect(const Geo1& geo1, const Geo2& geo2, ctype eps)
{
constexpr bool isWrapper1 = OCCUtilities::IsBRepWrapper<Geo1>::value;
constexpr bool isWrapper2 = OCCUtilities::IsBRepWrapper<Geo2>::value;
if constexpr (isWrapper1 && isWrapper2)
return intersectAndConvert(geo1.get(), geo2.get(), eps);
else if constexpr(isWrapper1 && !isWrapper2)
return intersectAndConvert(geo1.get(), geo2, eps);
else if constexpr(!isWrapper1 && isWrapper2)
return intersectAndConvert(geo1, geo2.get(), eps);
else
return intersectAndConvert(geo1, geo2, eps);
}
template<class Geo1, class Geo2, class ctype>
void registerIntersectionFunction(py::module& module,
const std::string& name1,
const std::string& name2)
{
using namespace py::literals;
const std::string doc = "Returns the intersection between the geometries " + name1 + "/" + name2;
const std::string docDef = doc + " (default geometric tolerance)";
const std::string docGiv = doc + " (given geometric tolerance)";
module.def("intersect",
py::overload_cast<const Geo1&, const Geo2&>(&Detail::intersect<Geo1, Geo2>),
docDef.c_str(), "geo1"_a, "geo2"_a);
module.def("intersect",
py::overload_cast<const Geo1&, const Geo2&, ctype>(&Detail::intersect<Geo1, Geo2, ctype>),
docGiv.c_str(), "geo1"_a, "geo2"_a, "eps"_a);
}
} // end namespace Detail
namespace py = pybind11;
template<class ctype>
void registerIntersectionFunctions(py::module& module)
{
using Segment = Frackit::Segment<ctype, 3>;
using Quad = Frackit::Quadrilateral<ctype, 3>;
using Polygon = Frackit::Polygon<ctype, 3>;
using Disk = Frackit::Disk<ctype>;
using CylSurf = Frackit::CylinderSurface<ctype>;
using FaceWrapper = Frackit::Python::OCCUtilities::FaceWrapper;
Detail::registerIntersectionFunction<Segment, Segment, ctype>(module, "Segment", "Segment");
Detail::registerIntersectionFunction<Quad, Quad, ctype>(module, "Quadrilateral", "Quadrilateral");
Detail::registerIntersectionFunction<Polygon, Polygon, ctype>(module, "Polygon", "Polygon");
Detail::registerIntersectionFunction<Disk, Disk, ctype>(module, "Disk", "Disk");
Detail::registerIntersectionFunction<FaceWrapper, FaceWrapper, ctype>(module, "TopoDS_Face_Wrapper", "TopoDS_Face_Wrapper");
Detail::registerIntersectionFunction<Quad, Disk, ctype>(module, "Quadrilateral", "Disk");
Detail::registerIntersectionFunction<Disk, Quad, ctype>(module, "Disk", "Quadrilateral");
Detail::registerIntersectionFunction<FaceWrapper, Disk, ctype>(module, "TopoDS_Face_Wrapper", "Disk");
Detail::registerIntersectionFunction<Disk, FaceWrapper, ctype>(module, "Disk", "TopoDS_Face_Wrapper");
Detail::registerIntersectionFunction<FaceWrapper, Quad, ctype>(module, "TopoDS_Face_Wrapper", "Quadrilateral");
Detail::registerIntersectionFunction<Quad, FaceWrapper, ctype>(module, "Quadrilateral", "TopoDS_Face_Wrapper");
Detail::registerIntersectionFunction<FaceWrapper, Polygon, ctype>(module, "TopoDS_Face_Wrapper", "Polygon");
Detail::registerIntersectionFunction<Polygon, FaceWrapper, ctype>(module, "Polygon", "TopoDS_Face_Wrapper");
Detail::registerIntersectionFunction<CylSurf, Disk, ctype>(module, "CylinderSurface", "Disk");
Detail::registerIntersectionFunction<Disk, CylSurf, ctype>(module, "Disk", "CylinderSurface");
Detail::registerIntersectionFunction<CylSurf, Quad, ctype>(module, "CylinderSurface", "Quadrilateral");
Detail::registerIntersectionFunction<Quad, CylSurf, ctype>(module, "Quadrilateral", "CylinderSurface");
Detail::registerIntersectionFunction<CylSurf, Polygon, ctype>(module, "CylinderSurface", "Polygon");
Detail::registerIntersectionFunction<Polygon, CylSurf, ctype>(module, "Polygon", "CylinderSurface");
Detail::registerIntersectionFunction<CylSurf, FaceWrapper, ctype>(module, "CylinderSurface", "TopoDS_Face_Wrapper");
Detail::registerIntersectionFunction<FaceWrapper, CylSurf, ctype>(module, "TopoDS_Face_Wrapper", "CylinderSurface");
}
} // end namespace Frackit::Python
#endif
......@@ -19,6 +19,8 @@
#ifndef FRACKIT_PYTHON_IO_GMSH_WRITER_HH
#define FRACKIT_PYTHON_IO_GMSH_WRITER_HH
#include <pybind11/pybind11.h>
#include <frackit/io/gmshwriter.hh>
#include <frackit/entitynetwork/entitynetwork.hh>
#include <frackit/entitynetwork/containedentitynetwork.hh>
......
add_subdirectory(common)
add_subdirectory(entitynetwork)
add_subdirectory(geometry)
add_subdirectory(intersection)
add_subdirectory(io)
add_subdirectory(magnitude)
add_subdirectory(occutilities)
......
frackit_symlink_or_copy(FILES __init__.py)
pybind11_add_module(_intersection _intersection.cc)
target_link_libraries(_intersection PRIVATE ${OCC_LIBS})
from ._intersection import *
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*****************************************************************************
* See the file COPYING for full copying permissions. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*****************************************************************************/
#include <pybind11/pybind11.h>
#include <frackit/python/intersection/emptyintersection.hh>
#include <frackit/python/intersection/intersect.hh>
PYBIND11_MODULE(_intersection, module)
{
Frackit::Python::registerEmptyIntersection<double>(module);
Frackit::Python::registerIntersectionFunctions<double>(module);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment