Commit 28707a55 authored by Dennis Gläser's avatar Dennis Gläser
Browse files

[constraints] use more verbose result type

parent cc2fb1ed
......@@ -121,6 +121,9 @@ EntityNetworkConstraints<ST> makeDefaultConstraints()
template<class ST, class AE>
class EntityNetworkConstraints
{
using Result = ConstraintsEvaluation;
using Violation = typename Result::Violation;
public:
//! Export type used for constraints
using Scalar = ST;
......@@ -128,6 +131,9 @@ public:
//! Exort the engine used for angle computations
using AngleComputationEngine = AE;
//! Export the result of an evaluation
using ResultType = Result;
/*!
* \brief Default constructor.
* \note This is only available if the engines are default constructible
......@@ -217,10 +223,12 @@ public:
* \brief Check if a pair of geometries fulfills the constraints
* \param geo1 The first geometry
* \param geo2 The second geometry
* \returns True if all constraints are fulfilled, false otherwise
* \return ConstraintsEvaluation type, which emulates true if all
* constraints are fulfilled, false otherwise. Moreover,
* it stores the information which violation was detected.
*/
template<class Geo1, class Geo2>
bool evaluate(const Geo1& geo1, const Geo2& geo2) const
ResultType evaluate(const Geo1& geo1, const Geo2& geo2) const
{
// if the provided geometries are pointers (we support shared_ptr here)
// to the abstract base class, we have to first cast them into the derived types
......@@ -258,14 +266,18 @@ public:
* \tparam Geo2 The geometry type of the entity to be checked
* \param entitySet An entity set
* \param entity The geometry of the entity to be checked
* \returns True if all constraints are fulfilled, false otherwise
* \return ConstraintsEvaluation type, which emulates true if all
* constraints are fulfilled, false otherwise. Moreover,
* it stores the information which violation was detected.
*/
template<class Geo1, class Geo2>
bool evaluate(const std::vector<Geo1>& entitySet, const Geo2& entity) const
ResultType evaluate(const std::vector<Geo1>& entitySet, const Geo2& entity) const
{
return std::all_of(entitySet.begin(),
entitySet.end(),
[&] (const auto& e) { return evaluate(e, entity); });
for (const auto& e : entitySet)
if (const auto res = evaluate(e, entity); !res)
return res;
return {Violation::none};
}
/*!
......@@ -275,10 +287,12 @@ public:
* \tparam Geo2 The geometry type of the entities in the set
* \param entity The geometry of the entity to be checked
* \param entitySet An entity set
* \returns True if all constraints are fulfilled, false otherwise
* \return ConstraintsEvaluation type, which emulates true if all
* constraints are fulfilled, false otherwise. Moreover,
* it stores the information which violation was detected.
*/
template<class Geo1, class Geo2>
bool evaluate(const Geo1& entity, const std::vector<Geo2>& entitySet) const
ResultType evaluate(const Geo1& entity, const std::vector<Geo2>& entitySet) const
{ return evaluate(entitySet, entity); }
/*!
......@@ -288,14 +302,18 @@ public:
* \tparam Geo2 The geometry type of the entities in the second set
* \param entitySet1 The first entity set
* \param entitySet2 The second entity set
* \returns True if all constraints are fulfilled, false otherwise
* \return ConstraintsEvaluation type, which emulates true if all
* constraints are fulfilled, false otherwise. Moreover,
* it stores the information which violation was detected.
*/
template<class Geo1, class Geo2>
bool evaluate(const std::vector<Geo1>& entitySet1, const std::vector<Geo2>& entitySet2) const
ResultType evaluate(const std::vector<Geo1>& entitySet1, const std::vector<Geo2>& entitySet2) const
{
return std::all_of(entitySet1.begin(),
entitySet1.end(),
[&] (const auto& entity1) { return evaluate(entity1, entitySet2); });
for (const auto& e1 : entitySet1)
if (const auto res = evaluate(e1, entitySet2); !res)
return res;
return {Violation::none};
}
private:
......@@ -306,7 +324,7 @@ private:
* \returns True if all constraints are fulfilled, false otherwise
*/
template<class Geo1, class Geo2>
bool evaluate_(const Geo1& geo1, const Geo2& geo2) const
ResultType evaluate_(const Geo1& geo1, const Geo2& geo2) const
{
static constexpr int dim = DimensionalityTraits<Geo1>::geometryDimension();
static_assert(dim == DimensionalityTraits<Geo2>::geometryDimension(),
......@@ -314,40 +332,44 @@ private:
const bool checkIs = useMinIsMagnitude_ || useMinIsAngle_ || useMinIsDistance_;
if (!checkIs && !useMinDistance_)
return true;
return {Violation::none};
const auto isection = !useIntersectionEps_ ? intersect(geo1, geo2)
: intersect(geo1, geo2, intersectionEps_);
if ( !isEmptyIntersection(isection) )
{
// check if dimensionality constraint is violated
// check if dimensionality constraint is violated
if (!allowEquiDimIS_ && !ConstraintImpl::isAdmissibleDimension(isection, dim-1))
return false;
return {Violation::intersectionDimension};
// magnitude constraint
if ( useMinIsMagnitude_ && !ConstraintImpl::isAdmissibleMagnitude(isection, minIsMagnitude_) )
return false;
return {Violation::intersectionMagnitude};
// angle constraint
if ( useMinIsAngle_ && angleEngine_(geo1, geo2, isection) < minIsAngle_ )
return false;
return {Violation::intersectionAngle};
// constraint on distance of intersection to geometry boundaries
if ( !useMinIsDistance_ )
return true;
return {Violation::none};
using namespace ConstraintImpl;
if (!isAdmissibleDistanceToBoundary(isection, geo1, minIsDistance_))
return false;
return isAdmissibleDistanceToBoundary(isection, geo2, minIsDistance_);
return {Violation::intersectionDistance};
if (!isAdmissibleDistanceToBoundary(isection, geo2, minIsDistance_))
return {Violation::intersectionDistance};
}
// no intersection - check distance constraint
else if (useMinDistance_)
return computeDistance(geo1, geo2) >= minDistance_;
{
if (computeDistance(geo1, geo2) < minDistance_)
return {Violation::distance};
}
return true;
return {Violation::none};
}
AngleComputationEngine angleEngine_; //! Algorithms to compute angles between intersecting geometries
......
......@@ -57,6 +57,9 @@ public:
//! export underlying constraints type
using Constraints = C;
//! export evaluation result type
using ResultType = typename C::ResultType;
/*!
* \brief Add a constraint that should be fulfilled
* between the two entity sets defined in the
......@@ -88,10 +91,12 @@ public:
* \param id The id of the entity set to which the entity belongs.
*/
template<class EntitySets, class Entity>
bool evaluate(const EntitySets& entitySets,
const Entity& entity,
const Id& id)
ResultType evaluate(const EntitySets& entitySets,
const Entity& entity,
const Id& id) const
{
using Violation = typename ResultType::Violation;
auto it = constraintsIndexMap_.find(id.get());
if (it == constraintsIndexMap_.end())
throw std::runtime_error("evaluate: no constraints set for given id");
......@@ -102,19 +107,19 @@ public:
const auto& constraints = constraints_[idxPair.second];
// lambda for the evaluation of the constraints
bool isAdmissible;
ResultType res{Violation::none};
auto evalConstraintOnSet = [&] (const auto& entitySet) -> void
{ isAdmissible = constraints.evaluate(entitySet, entity); };
{ res = constraints.evaluate(entitySet, entity); };
// applyOnSet() returns false if lambda was not applied
// This is the case e.g. when the set is empty. Here,
// return false only if applyOnSet() was successful.
if (entitySets.applyOnSet(otherId, evalConstraintOnSet))
if (!isAdmissible)
return false;
if (!res)
return res;
}
return true;
return {Violation::none};
}
private:
......
Markdown is supported
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