Add a function that only constructs a point intersection for 3 planes

This commit is contained in:
Andreas Fabri 2020-10-01 11:11:32 +01:00
parent 48d9971386
commit eafad68789
8 changed files with 224 additions and 30 deletions

View File

@ -560,20 +560,7 @@ struct Envelope {
std::cout << "todo degeneration handling" << std::endl;
//n = Point_3(rand(), rand(), rand())} };
}
/*
CGAL::cpp11::result_of<eIntersect_3(ePlane_3, ePlane_3, ePlane_3)>::type
result = CGAL::intersection(tri, facet1, facet2);
if(! result){
#ifdef TRACE
std::cout << "there must be an intersection 4" << std::endl;
#endif
return 0;
}
const ePoint_3* ipp = boost::get<ePoint_3>(&*result);
CGAL_assertion(ipp != nullptr);
const ePoint_3& ip = *ipp;
*/
int o1 = int(CGAL::orientation(n,tp,tq, ip));
int o2 = int(CGAL::orientation(n,tq,tr, ip));
@ -806,16 +793,10 @@ struct Envelope {
}
int inter = 0;
ePoint_3* ipp;
CGAL::cpp11::result_of<eIntersect_3(ePlane_3, ePlane_3, ePlane_3)>::type
result = CGAL::intersection(tri_eplane, prism[cutp[i]].eplane, prism[cutp[j]].eplane);
if(result){
ipp = boost::get<ePoint_3>(&*result);
if(ipp != nullptr){
const ePoint_3& ip = *ipp;
inter = is_3_triangle_cut_float_fast(tri0, tri1, tri2, ip );
}
boost::optional<ePoint_3> ipp = CGAL::intersection_point(tri_eplane, prism[cutp[i]].eplane, prism[cutp[j]].eplane);
if(ipp){
inter = is_3_triangle_cut_float_fast(tri0, tri1, tri2, *ipp);
}
// this was for a fast float check
if (inter == 2)
@ -1933,11 +1914,15 @@ int main(int argc, char* argv[])
Point_3 v0 = env_vertices[ii];
Point_3 v1 = env_vertices[ij];
Point_3 v2 = env_vertices[ik];
/*
{
std::ofstream query("query.off");
query << "OFF\n" << "3 1 0\n" << v0 << std::endl << v1 << std::endl << v2 << std::endl << "3 0 1 2" << std::endl;
}
*/
bbb = envelope(v0, v1, v2);
std::cout << t.time() << " sec." << std::endl;
}
if(bbb){
@ -1948,17 +1933,21 @@ int main(int argc, char* argv[])
return 0;
}
int inside_count = 0;
int outside_count = 0;
std::ofstream inside("inside.txt");
std::ofstream outside("outside.txt");
for(int i = 0; i < env_vertices.size(); i+=10){
for(int i = 0; i < env_vertices.size() ; i+=10){
for(int j = i+1; j < env_vertices.size(); j+= 10){
for(int k = j+1; k < env_vertices.size(); k+=10){
if( ( i != j) && (i != k) && (j != k)){
if(! CGAL::collinear(env_vertices[i], env_vertices[j],env_vertices[k])){
if(envelope(env_vertices[i], env_vertices[j], env_vertices[k])){
inside_count++;
inside << i << " " << j << " "<< k <<std::endl;
} else{
outside_count++;
outside << i << " " << j << " "<< k <<std::endl;
}
}
@ -1966,7 +1955,8 @@ int main(int argc, char* argv[])
}
}
}
std::cout << inside_count << " " << outside_count << std::endl;
std::cout << t.time() << " sec." << std::endl;
return 0;
}

View File

@ -54,6 +54,7 @@ int main(int argc, char* argv[]) {
fastEnvelope::Vector3 v2 = env_vertices[ik];
std::array<fastEnvelope::Vector3, 3> tria = {v0, v1, v2};
bool bbb = envelope.is_outside(tria);
std::cout << t.time() << " sec." << std::endl;
if(bbb){
std::cout << "outside the envelope" << std::endl;
}else{
@ -62,6 +63,8 @@ int main(int argc, char* argv[]) {
return 0;
}
int inside_count = 0;
int outside_count = 0;
std::ofstream inside("insideE.txt");
std::ofstream outside("outsideE.txt");
@ -75,14 +78,18 @@ int main(int argc, char* argv[]) {
if(! CGAL::collinear(p,q,r)){
std::array<fastEnvelope::Vector3, 3> f = { env_vertices[i], env_vertices[j], env_vertices[k] };
if(! envelope.is_outside(f)){
inside << i << " " << j << " "<< k <<std::endl;
inside_count++;
//inside << i << " " << j << " "<< k <<std::endl;
} else{
outside << i << " " << j << " "<< k <<std::endl;
outside_count++;
//outside << i << " " << j << " "<< k <<std::endl;
}
}
}
}
}
}
}
std::cout << inside_count << " " << outside_count << std::endl;
std::cout << t.time() << " sec." << std::endl;
}

View File

@ -353,6 +353,53 @@ class Lazy_rep_n :
#endif
};
template<typename AT, typename ET, typename AC, typename EC, typename E2A, typename...L>
class Lazy_rep_optional_n :
public Lazy_rep< AT, ET, E2A >, private EC
{
// Lazy_rep_0 does not inherit from EC or take a parameter AC. It has different constructors.
static_assert(sizeof...(L)>0, "Use Lazy_rep_0 instead");
template <class Ei, class Ai, class E2Ai, class Ki> friend class Lazy_kernel_base;
mutable std::tuple<L...> l; // L...l; is not yet allowed.
const EC& ec() const { return *this; }
template<std::size_t...I>
void update_exact_helper(std::index_sequence<I...>) const {
this->et = new ET( * ec()( CGAL::exact( std::get<I>(l) ) ... ) );
this->at = E2A()(*(this->et));
l = std::tuple<L...>{};
}
public:
void update_exact() const {
update_exact_helper(std::make_index_sequence<sizeof...(L)>{});
}
template<class...LL>
Lazy_rep_optional_n(const AT& a, const EC& ec, LL&&...ll) :
Lazy_rep<AT, ET, E2A>(a), EC(ec), l(std::forward<LL>(ll)...)
{
this->set_depth((std::max)({ -1, (int)CGAL::depth(ll)...}) + 1);
}
#ifdef CGAL_LAZY_KERNEL_DEBUG
private:
template<std::size_t...I>
void print_dag_helper(std::ostream& os, int level, std::index_sequence<I...>) const {
this->print_at_et(os, level);
if(this->is_lazy()){
# ifdef CGAL_LAZY_KERNEL_DEBUG_SHOW_TYPEID
CGAL::msg(os, level, typeid(AC).name());
# endif
CGAL::msg(os, level, "DAG with " "3" " child nodes:");
using expander = int[];
expander{0,(CGAL::print_dag(std::get<I>(l), os, level+1),0)...};
}
}
public:
void print_dag(std::ostream& os, int level) const {
print_dag_helper(os, level, std::make_index_sequence<sizeof...L>{});
}
#endif
};
//____________________________________________________________
// The rep for the leaf node
@ -801,6 +848,56 @@ struct Lazy_construction_bbox
};
template <typename LK, typename AC, typename EC>
struct Lazy_construction_optional
{
static const bool Protection = true;
typedef typename LK::Approximate_kernel AK;
typedef typename LK::Exact_kernel EK;
typedef typename LK::E2A E2A;
typedef boost::optional<typename LK::Point_3> result_type;
CGAL_NO_UNIQUE_ADDRESS AC ac;
CGAL_NO_UNIQUE_ADDRESS EC ec;
// for Intersect_point_3 with 3 Plane_3
template <typename L1>
result_type operator()(const L1& l1, const L1& l2, const L1& l3) const
{
Protect_FPU_rounding<Protection> P;
try {
boost::optional<typename AK::Point_3> oap = ac(CGAL::approx(l1),CGAL::approx(l2),CGAL::approx(l3));
if(oap == boost::none){
return boost::none;
}
// Now we have to construct a rep for a lazy point with the three lazy planes.
typedef Lazy_rep_optional_n<typename AK::Point_3, typename EK::Point_3, AC, EC, E2A, L1, L1, L1> LazyPointRep;
const typename AK::Point_3 ap = *oap;
LazyPointRep *rep = new LazyPointRep(ap, ec, l1, l2, l3);
typename LK::Point_3 lp(rep);
return boost::make_optional(lp);
} catch (Uncertain_conversion_exception&) {
Protect_FPU_rounding<!Protection> P2(CGAL_FE_TONEAREST);
boost::optional<typename EK::Point_3> oep = ec(CGAL::exact(l1),CGAL::exact(l2),CGAL::exact(l3));
if(oep == boost::none){
return boost::none;
}
typedef Lazy_rep_0<typename AK::Point_3, typename EK::Point_3,E2A> LazyPointRep;
const typename EK::Point_3 ep = *oep;
LazyPointRep *rep = new LazyPointRep(ep);
typename LK::Point_3 lp(rep);
return boost::make_optional(lp);
}
// AF can we get here??
return boost::none;
}
};
template <typename LK, typename AC, typename EC>
struct Lazy_construction_nt {
Lazy_construction_nt(){}

View File

@ -81,7 +81,7 @@ struct Lazy_result_type
class Enum_holder {
protected:
enum { NONE, NT, VARIANT, OBJECT, BBOX };
enum { NONE, NT, VARIANT, OBJECT, BBOX, OPTIONAL };
};
} // internal
@ -178,6 +178,7 @@ private:
// The case distinction goes as follows:
// result_type == FT => NT
// result_type == Object => Object
// result_type == boost::optional => OPTIONAL
// result_type == Bbox_2 || result_type == Bbox_3 => BBOX
// default => NONE
// no result_type => NONE
@ -213,6 +214,7 @@ private:
CGAL_WRAPPER_TRAIT(Intersect_2, VARIANT)
CGAL_WRAPPER_TRAIT(Intersect_3, VARIANT)
CGAL_WRAPPER_TRAIT(Intersect_point_3, OPTIONAL)
CGAL_WRAPPER_TRAIT(Compute_squared_radius_2, NT)
CGAL_WRAPPER_TRAIT(Compute_x_3, NT)
CGAL_WRAPPER_TRAIT(Compute_y_3, NT)
@ -253,6 +255,12 @@ private:
struct apply { typedef Lazy_construction_bbox<Kernel, AKC, EKC> type; };
};
template <typename Construction>
struct Select_wrapper_impl<Construction, OPTIONAL> {
template<typename Kernel, typename AKC, typename EKC>
struct apply { typedef Lazy_construction_optional<Kernel, AKC, EKC> type; };
};
template <typename Construction>
struct Select_wrapper : Select_wrapper_impl<Construction> {};
@ -307,6 +315,21 @@ public:
// typedef void Compute_z_3; // to detect where .z() is called
// typedef void Construct_point_3; // to detect where the ctor is called
/*
struct Intersect_point_3
{
typedef typename Kernel_::Point_3 Point_3;
typedef typename Kernel_::Plane_3 Plane_3;
boost::optional<Point_3>
operator()(const Plane_3& p0, const Plane_3& p1, const Plane_3& p2) const
{
std::cout << "get here" << std::endl;
std::cout << typeid(Plane_3).name() << std::endl;
return boost::none;
}
};
*/
struct Compute_weight_2 : public BaseClass::Compute_weight_2
{
typedef typename Kernel_::FT FT;
@ -491,7 +514,12 @@ public:
};
/*
Intersect_point_3 construct_intersect_point_3_object() const
{
return Intersect_point_3();
}
*/
Construct_point_2 construct_point_2_object() const
{
return Construct_point_2();

View File

@ -21,6 +21,16 @@
namespace CGAL {
CGAL_INTERSECTION_FUNCTION_SELF(Plane_3, 3)
CGAL_DO_INTERSECT_FUNCTION_SELF(Plane_3, 3)
template < class K >
inline
boost::optional<typename K::Point_3>
intersection_point(const Plane_3<K>& p0, const Plane_3<K>& p1, const Plane_3<K>& p2)
{
return K().intersect_point_3_object()(p0, p1, p2);
}
}
#endif // CGAL_INTERSECTIONS_3_PLANE_3_PLANE_3_H

View File

@ -182,6 +182,49 @@ intersection(const typename K::Plane_3 &plane1,
return intersection_return<typename K::Intersect_3, typename K::Plane_3, typename K::Plane_3>(plane1);
}
// triple plane intersection
template <class K>
boost::optional<typename K::Point_3>
intersection_point(const typename K::Plane_3 &plane1,
const typename K::Plane_3 &plane2,
const typename K::Plane_3 &plane3,
const K& k)
{
typedef typename boost::optional<typename K::Point_3> result_type;
typedef typename K::FT FT;
const FT &m00 = plane1.a();
const FT &m01 = plane1.b();
const FT &m02 = plane1.c();
const FT &b0 = plane1.d();
const FT &m10 = plane2.a();
const FT &m11 = plane2.b();
const FT &m12 = plane2.c();
const FT &b1 = plane2.d();
const FT &m20 = plane3.a();
const FT &m21 = plane3.b();
const FT &m22 = plane3.c();
const FT &b2 = plane3.d();
const FT den = - determinant(m00, m01, m02,
m10, m11, m12,
m20, m21, m22);
if(den == FT(0)){
return boost::none;
}
const FT num1 = determinant(b0, m01, m02,
b1, m11, m12,
b2, m21, m22);
const FT num2 = determinant(m00, b0, m02,
m10, b1, m12,
m20, b2, m22);
const FT num3 = determinant(m00, m01, b0,
m10, m11, b1,
m20, m21, b2);
return boost::make_optional(typename K::Point_3(num1/den, num2/den, num3/den));
}
template <class K>
boost::optional< boost::variant<typename K::Point_3,
typename K::Line_3,

View File

@ -3567,6 +3567,23 @@ namespace CommonKernelFunctors {
{ return Intersections::internal::intersection(pl1, pl2, pl3, K() ); }
};
template <typename K>
class Intersect_point_3
{
public:
typedef typename K::Point_3 Point_3;
typedef typename K::Plane_3 Plane_3;
typedef typename boost::optional<Point_3> result_type;
result_type
operator()(const Plane_3& pl1, const Plane_3& pl2, const Plane_3& pl3) const
{
return Intersections::internal::intersection_point(pl1, pl2, pl3, K() );
}
};
template <typename K>
class Is_degenerate_2
{

View File

@ -542,6 +542,8 @@ CGAL_Kernel_cons(Intersect_2,
intersect_2_object)
CGAL_Kernel_cons(Intersect_3,
intersect_3_object)
CGAL_Kernel_cons(Intersect_point_3,
intersect_point_3_object)
CGAL_Kernel_pred(Is_degenerate_2,
is_degenerate_2_object)
CGAL_Kernel_pred_RT(Is_degenerate_3,