mirror of https://github.com/CGAL/cgal
casting_2: added pullout_direction_single_mold_translation
This commit is contained in:
parent
9f240310d8
commit
f04c83fb15
|
|
@ -4,10 +4,14 @@
|
|||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_2.h>
|
||||
#include <CGAL/top_edges_single_mold_translational_casting_2.h>
|
||||
#include <CGAL/pullout_directions_single_mold_translational_casting_2.h>
|
||||
#include <CGAL/is_pullout_direction_single_mold_translational_casting_2.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
typedef Kernel::Direction_2 Direction_2;
|
||||
typedef Kernel::Vector_2 Vector_2;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
typedef std::pair<Direction_2, Direction_2> Direction_range;
|
||||
typedef std::pair<size_t, Direction_range> Top_edge;
|
||||
|
||||
|
|
@ -29,9 +33,11 @@ int main(int argc, char* argv[])
|
|||
|
||||
auto poly_orientation = pgn.orientation();
|
||||
std::list<Top_edge> top_edges;
|
||||
|
||||
|
||||
//example for top_edges_single_mold_translational_casting_2
|
||||
SMS::top_edges_single_mold_translational_casting_2
|
||||
(pgn, std::back_inserter(top_edges));
|
||||
|
||||
if (top_edges.empty())
|
||||
std::cout << "The polygon is not castable!" << std::endl;
|
||||
else {
|
||||
|
|
@ -44,6 +50,55 @@ int main(int argc, char* argv[])
|
|||
<< std::endl<< std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << "-----------------------------------"<< std::endl;
|
||||
|
||||
//example for pullout_directions_single_mold_translational_casting_2
|
||||
int index =0;
|
||||
for (auto e_it = pgn.edges_begin(); e_it != pgn.edges_end(); ++e_it, ++index)
|
||||
|
||||
{
|
||||
|
||||
std::pair<bool, std::pair< Kernel::Direction_2,
|
||||
Kernel::Direction_2> > res = SMS::pullout_directions_single_mold_translational_casting_2(pgn,e_it);
|
||||
if (res.first)
|
||||
{
|
||||
std::cout << "The polygon is castable using edge "<<index<<" in range " << res.second.first
|
||||
<< " to " << res.second.second
|
||||
<< std::endl<< std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "The polygon is not castable using edge "<<index<<std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << "-----------------------------------"<< std::endl;
|
||||
//example for is_pullout_directions_single_mold_translational_casting_2 that accepts the edge
|
||||
for (auto e_it = pgn.edges_begin(); e_it != pgn.edges_end(); ++e_it, ++index)
|
||||
{
|
||||
auto segment_outer_circle =
|
||||
SMS::internal::get_segment_outer_circle<Kernel>(*e_it, poly_orientation);
|
||||
Direction_2 d = segment_outer_circle.first;
|
||||
d= d.perpendicular(CGAL::CLOCKWISE);
|
||||
bool res = SMS::is_pullout_direction_single_mold_translational_casting_2(pgn,e_it,d);
|
||||
std::cout << "The polygon is "<<(res?"":"not ") <<"castable using edge "<<index<<" in vartical translation ("<<d<<")"<< std::endl;
|
||||
|
||||
}
|
||||
std::cout << "-----------------------------------"<< std::endl;
|
||||
|
||||
//example for is_pullout_directions_single_mold_translational_casting_2 that do not accepts the edge
|
||||
{
|
||||
Vector_2 v (Point_2(0,0),Point_2(1,0));
|
||||
Direction_2 d(v);
|
||||
std::pair<bool, size_t>
|
||||
res = SMS::is_pullout_direction_single_mold_translational_casting_2(pgn,d);
|
||||
if (res.first)
|
||||
{
|
||||
std::cout << "The polygon is castable in direction d ("<<d<<") using edge "<<res.second<<std::endl;
|
||||
|
||||
}
|
||||
else {
|
||||
std::cout << "The polygon is not castable in direction d ("<<d<<")"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
8
|
||||
-1 0 -7 7 0 1 7 7 1 0 7 -7 0 -1 -7 -7
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
4
|
||||
0 -1 1 0 1 1 0 7
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
3
|
||||
0 0 1 0 1 1
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* utils.h
|
||||
*
|
||||
* Created on: Jan 17, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef SET_MOVABLE_SEPARABILITY_2_INCLUDE_CGAL_SET_MOVABLE_SEPARABILITY_2_UTILS_H_
|
||||
#define SET_MOVABLE_SEPARABILITY_2_INCLUDE_CGAL_SET_MOVABLE_SEPARABILITY_2_UTILS_H_
|
||||
#include <CGAL/enum.h>
|
||||
#include <CGAL/Polygon_2.h>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
namespace Set_movable_separability_2 {
|
||||
namespace internal {
|
||||
|
||||
/*! \fn std::pair<typename Kernel::Direction_2,typename Kernel::Direction_2> get_segment_outer_circle(typename Kernel::Segment_2 seg, CGAL::Orientation orientation)
|
||||
* \param[in] seg the polygon segment
|
||||
* \param[in] orientation the orientation of the segment (and the polygon).
|
||||
* if CLOCKWISE then the outer half circle is to the left.
|
||||
* \return the open outer half-circle of the edge.
|
||||
*/
|
||||
template <typename Kernel>
|
||||
inline std::pair<typename Kernel::Direction_2, typename Kernel::Direction_2>
|
||||
get_segment_outer_circle(const typename Kernel::Segment_2 seg,
|
||||
const CGAL::Orientation orientation)
|
||||
{
|
||||
typename Kernel::Direction_2 forward( seg);
|
||||
typename Kernel::Direction_2 backward(-forward);
|
||||
return (orientation == CGAL::Orientation::CLOCKWISE) ?
|
||||
std::make_pair(backward, forward) : std::make_pair(forward, backward);
|
||||
}
|
||||
|
||||
template <typename Kernel>
|
||||
bool is_any_edge_colinear(const CGAL::Polygon_2<Kernel>& pgn)
|
||||
{
|
||||
typedef typename CGAL::Point_2<Kernel> Point_2;
|
||||
typedef typename CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
typedef typename Polygon_2::Vertex_const_iterator Vertex_const_iterator;
|
||||
Vertex_const_iterator vci = pgn.vertices_begin();
|
||||
Point_2 firstVar = *(vci++);
|
||||
Point_2 secondVar = *(vci++);
|
||||
Point_2 thirdVar = *(vci++);
|
||||
for (; vci != pgn.vertices_end(); ++vci) {
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *vci;
|
||||
if (CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
}
|
||||
vci = pgn.vertices_begin();
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *(vci++);
|
||||
if(CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *(vci++);
|
||||
if (CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
} // end of namespace internal
|
||||
} // end of namespace Set_movable_separability_2
|
||||
} // end of namespace CGAL
|
||||
|
||||
|
||||
|
||||
#endif /* SET_MOVABLE_SEPARABILITY_2_INCLUDE_CGAL_SET_MOVABLE_SEPARABILITY_2_UTILS_H_ */
|
||||
15
Set_movable_separability_2/include/CGAL/is_pullout_direction_single_mold_translational_casting_2.h
Normal file → Executable file
15
Set_movable_separability_2/include/CGAL/is_pullout_direction_single_mold_translational_casting_2.h
Normal file → Executable file
|
|
@ -20,6 +20,7 @@
|
|||
#include <CGAL/Polygon_2.h>
|
||||
#include <CGAL/enum.h>
|
||||
#include <limits>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace Set_movable_separability_2 {
|
||||
|
|
@ -43,8 +44,7 @@ namespace Set_movable_separability_2 {
|
|||
* does not have three consecutive collinear vertices.
|
||||
*/
|
||||
template <typename CastingTraits_2>
|
||||
bool
|
||||
is_pullout_direction_single_mold_translational_casting_2
|
||||
bool is_pullout_direction_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, size_t i,
|
||||
typename CastingTraits_2::Direction_2& d, CastingTraits_2& traits)
|
||||
{
|
||||
|
|
@ -79,8 +79,7 @@ is_pullout_direction_single_mold_translational_casting_2
|
|||
/*!
|
||||
*/
|
||||
template <typename CastingTraits_2>
|
||||
bool
|
||||
is_pullout_direction_single_mold_translational_casting_2
|
||||
bool is_pullout_direction_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, size_t i,
|
||||
typename CastingTraits_2::Direction_2& d)
|
||||
{
|
||||
|
|
@ -101,19 +100,20 @@ is_pullout_direction_single_mold_translational_casting_2
|
|||
*
|
||||
* \param[in] pgn the input polygon.
|
||||
* \param[in] d the pullout direction
|
||||
* \return pair<if the polygon can be pullout through some edge with direction d, the edge if the first part is true, else nondeterministic>
|
||||
* \return pair<if the polygon can be pullout through some edge with direction
|
||||
* d, the edge if the first part is true, else nondeterministic>
|
||||
*
|
||||
* \pre `png` must be non-degenerate (has at least 3 vertices),simple, and
|
||||
* does not have three consecutive collinear vertices.
|
||||
*/
|
||||
#define MAX_SIZE_T (std::numeric_limits<size_t>::max())
|
||||
|
||||
template <typename CastingTraits_2>
|
||||
std::pair<bool, size_t>
|
||||
is_pullout_direction_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn,
|
||||
typename CastingTraits_2::Direction_2& d, CastingTraits_2& traits)
|
||||
{
|
||||
|
||||
//NOT CHECKED AT ALL
|
||||
CGAL_precondition(pgn.is_simple());
|
||||
CGAL_precondition(!is_any_edge_colinear(pgn));
|
||||
|
|
@ -149,7 +149,8 @@ is_pullout_direction_single_mold_translational_casting_2
|
|||
/*!
|
||||
*/
|
||||
template <typename CastingTraits_2>
|
||||
bool is_pullout_direction_single_mold_translational_casting_2
|
||||
std::pair<bool, size_t>
|
||||
is_pullout_direction_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, size_t i,
|
||||
typename CastingTraits_2::Direction_2& d)
|
||||
{
|
||||
|
|
|
|||
150
Set_movable_separability_2/include/CGAL/pullout_directions_single_mold_translational_casting_2.h
Normal file → Executable file
150
Set_movable_separability_2/include/CGAL/pullout_directions_single_mold_translational_casting_2.h
Normal file → Executable file
|
|
@ -24,6 +24,133 @@ namespace CGAL {
|
|||
|
||||
namespace Set_movable_separability_2 {
|
||||
|
||||
|
||||
/*! Same as below with the additional traits argument.
|
||||
* \param[in] traits the traits to use.
|
||||
*
|
||||
* algorithm:
|
||||
* this function implements a very simple algorithm... it just keep at any stage the current
|
||||
* intersection in [firstClockwise,secondClockwise].
|
||||
* When a new semicircle appear the possible cases are as such:
|
||||
* (let f:=firstClockwise, s:=secondClockwise, a:=newSemicircleFirstClockwise , b:=newSemicircleSecondClockwise)
|
||||
* REMEBER THAT THIS ARE SEGMENTS ON A CIRCLE! NOT ON A LINE!
|
||||
* 1. [f,s] contained in [a,b]
|
||||
* f s * f s * f s * f s
|
||||
* a b * a b * a b * a b
|
||||
* _________________ * _________________ * _________________* _________________
|
||||
* f s * f s * f s * f s
|
||||
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
* 2. a contained in (f,s] and b is not / or in other words / s in [a,b) and f is not in [a,b] (it is enough to ask if s is in [a,b] since fs+ab is less than 2*pi)
|
||||
* f s * f s
|
||||
* a b * a b
|
||||
* _________________ * _________________
|
||||
* f s * fs
|
||||
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
* 3. b contained in [f,s) and a is not / or in other words / f in (a,b] and s is not in [a,b] (it is enough to ask if f is in [a,b] since fs is shorter the ab)
|
||||
* f s * f s
|
||||
* a b * a b
|
||||
* _________________ * _________________
|
||||
* f s * fs
|
||||
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
* 4. no intersection between [f,s] and [a,b] / case a: or in other words / f,s are not in [a,b]
|
||||
* f s * f s
|
||||
* b a * b a
|
||||
* _________________ * _________________
|
||||
* NO INTERSECTION! * NO INTERSECTION! (the only case in which this is possible is if (f,s) was not changes, and then (f,s) is an open arc)
|
||||
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
* 5. Illegal cases
|
||||
* f s * f s
|
||||
* a b * b a
|
||||
* __________________* __________________
|
||||
* THIS CASE CANT HAPPEN!! [a,b] is an semicircle, and (f,s) is a semicircle or less
|
||||
*/
|
||||
template <typename CastingTraits_2>
|
||||
std::pair<bool, std::pair<typename CastingTraits_2::Direction_2,
|
||||
typename CastingTraits_2::Direction_2> >
|
||||
pullout_directions_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, const typename CGAL::Polygon_2<CastingTraits_2>::Edge_const_iterator& i, CastingTraits_2& traits)
|
||||
{
|
||||
CGAL_precondition(pgn.is_simple());
|
||||
CGAL_precondition(!internal::is_any_edge_colinear(pgn));
|
||||
CGAL_precondition(pgn.size()>i);
|
||||
CGAL::Orientation poly_orientation = pgn.orientation();
|
||||
|
||||
typedef CastingTraits_2 Casting_traits_2;
|
||||
typename Casting_traits_2::Direction_2 clockFirst, clockSecond; //the returned range is [clockFirst,clockSecond]
|
||||
|
||||
|
||||
auto segment_outer_circle =
|
||||
internal::get_segment_outer_circle<Casting_traits_2>(*i, poly_orientation);
|
||||
clockFirst=segment_outer_circle.first;
|
||||
clockSecond=segment_outer_circle.second;
|
||||
//well theoretically, this is a bug since the current intersection is currently (clockFirst,clockSecond)
|
||||
//and not [clockFirst,clockSecond].. but this edges will surly change since we are in a polygon
|
||||
|
||||
bool isRangeSmallerThanSemicircle=false;
|
||||
auto cc_in_between = traits.counterclockwise_in_between_2_object();
|
||||
|
||||
for (auto e_it = pgn.edges_begin(); e_it != pgn.edges_end(); ++e_it) {
|
||||
if(e_it==i) continue;
|
||||
//std::cout<<"f "<<clockFirst<<" s "<<clockSecond<<std::endl;
|
||||
auto segment_outer_circle =
|
||||
internal::get_segment_outer_circle<Casting_traits_2>(*e_it, poly_orientation);
|
||||
// std::cout<<"a "<<segment_outer_circle.second<<" b "<<segment_outer_circle.first<<std::endl;
|
||||
|
||||
//notice that we are interested in the segment_inner_circle (segment_outer_circle.second,segment_outer_circle.first)
|
||||
if(!isRangeSmallerThanSemicircle)
|
||||
{
|
||||
if(segment_outer_circle.first==clockSecond && segment_outer_circle.second == clockFirst)
|
||||
{
|
||||
// std::cout<<"case 1b"<<std::endl<<std::endl;
|
||||
|
||||
// the arc is the range case 1b
|
||||
continue;
|
||||
}
|
||||
if(segment_outer_circle.first==clockFirst&& segment_outer_circle.second ==clockSecond )
|
||||
{
|
||||
// std::cout<<"case 4b"<<std::endl<<std::endl;
|
||||
|
||||
// the arc the opposite of the range case 4b
|
||||
return std::make_pair(false, std::make_pair(clockFirst, clockSecond));
|
||||
}
|
||||
isRangeSmallerThanSemicircle=true;
|
||||
}
|
||||
bool fBetweenAB = !cc_in_between(clockFirst,segment_outer_circle.second,segment_outer_circle.first);
|
||||
//is true if segment_outer_circle \in [first,clockFirst,clockSecond]
|
||||
bool sBetweenAB = !cc_in_between(clockSecond,segment_outer_circle.second,segment_outer_circle.first);
|
||||
//is true if segment_outer_circle \in [first,clockFirst,clockSecond]
|
||||
if (fBetweenAB && sBetweenAB)
|
||||
{
|
||||
// std::cout<<"case 1"<<std::endl<<std::endl;
|
||||
|
||||
//case 1 //surly not case 4b since [f,s] is less then a semicircle
|
||||
continue;
|
||||
}
|
||||
if (!fBetweenAB && sBetweenAB)
|
||||
{
|
||||
// std::cout<<"case 2"<<std::endl<<std::endl;
|
||||
|
||||
//case 2 - return a,s
|
||||
clockFirst = segment_outer_circle.second;
|
||||
}
|
||||
else if(fBetweenAB && !sBetweenAB)
|
||||
{
|
||||
// std::cout<<"case 3"<<std::endl<<std::endl;
|
||||
|
||||
//case 3 - return f,b
|
||||
clockSecond = segment_outer_circle.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cout<<"case 4a"<<std::endl<<std::endl;
|
||||
|
||||
//case 4a
|
||||
return std::make_pair(false, std::make_pair(clockFirst, clockSecond));
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(true, std::make_pair(clockFirst, clockSecond));
|
||||
}
|
||||
/*! Given a simple polygon and an edge of the polygon, this function determines
|
||||
* whether a cavity (of a mold in the plane) that has the shape of the polygon
|
||||
* can be used so that the polygon could be casted in the mold with the input
|
||||
|
|
@ -42,6 +169,7 @@ namespace Set_movable_separability_2 {
|
|||
* is a closed range of pull-out directions represented as a pair
|
||||
* of the extreme directions in the range. If the input edge is not
|
||||
* a valid top edge, the range is nondeterministic.
|
||||
* a pair of Directions is build this way [firstClockwise,secondClockwise]
|
||||
*
|
||||
* \pre `png` must be non-degenerate (has at least 3 vertices), simple, and
|
||||
* does not have three consecutive collinear vertices.
|
||||
|
|
@ -50,29 +178,17 @@ template <typename CastingTraits_2>
|
|||
std::pair<bool, std::pair<typename CastingTraits_2::Direction_2,
|
||||
typename CastingTraits_2::Direction_2> >
|
||||
pullout_directions_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, size_t i, CastingTraits_2& traits)
|
||||
{
|
||||
typedef CastingTraits_2 Casting_traits_2;
|
||||
typename Casting_traits_2::Direction_2 d1, d2;
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn,
|
||||
|
||||
return std::make_pair(false, std::make_pair(d1, d2));
|
||||
}
|
||||
|
||||
template <typename CastingTraits_2>
|
||||
std::pair<bool, std::pair<typename CastingTraits_2::Direction_2,
|
||||
typename CastingTraits_2::Direction_2> >
|
||||
/*! Same as above with the additional traits argument.
|
||||
* \param[in] pgn the input polygon.
|
||||
* \param[in] i the index of an edge in pgn.
|
||||
* \param[in] traits the traits to use.
|
||||
*/
|
||||
pullout_directions_single_mold_translational_casting_2
|
||||
(const CGAL::Polygon_2<CastingTraits_2>& pgn, size_t i)
|
||||
const typename CGAL::Polygon_2<CastingTraits_2>::Edge_const_iterator& i)
|
||||
{
|
||||
|
||||
CastingTraits_2 traits;
|
||||
return pullout_directions_single_mold_translational_casting_2(pgn, i, traits);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end of namespace Set_movable_separability_2
|
||||
} // end of namespace CGAL
|
||||
|
||||
|
|
|
|||
56
Set_movable_separability_2/include/CGAL/top_edges_single_mold_translational_casting_2.h
Normal file → Executable file
56
Set_movable_separability_2/include/CGAL/top_edges_single_mold_translational_casting_2.h
Normal file → Executable file
|
|
@ -25,6 +25,7 @@
|
|||
#include <CGAL/enum.h>
|
||||
|
||||
#include "Set_movable_separability_2/Circle_arrangment.h"
|
||||
#include "Set_movable_separability_2/Utils.h"
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -42,58 +43,12 @@ namespace Set_movable_separability_2 {
|
|||
* fitting segment. This arc is always open half circle.
|
||||
*/
|
||||
|
||||
/*! \fn std::pair<typename Kernel::Direction_2,typename Kernel::Direction_2> get_segment_outer_circle(typename Kernel::Segment_2 seg, CGAL::Orientation orientation)
|
||||
* \param[in] seg the polygon segment
|
||||
* \param[in] orientation the orientation of the segment (and the polygon).
|
||||
* if CLOCKWISE then the outer half circle is to the left.
|
||||
* \return the open outer half-circle of the edge.
|
||||
*/
|
||||
template <typename Kernel>
|
||||
inline std::pair<typename Kernel::Direction_2, typename Kernel::Direction_2>
|
||||
get_segment_outer_circle(const typename Kernel::Segment_2 seg,
|
||||
const CGAL::Orientation orientation)
|
||||
{
|
||||
typename Kernel::Direction_2 forward( seg);
|
||||
typename Kernel::Direction_2 backward(-forward);
|
||||
return (orientation == CGAL::Orientation::CLOCKWISE) ?
|
||||
std::make_pair(backward, forward) : std::make_pair(forward, backward);
|
||||
}
|
||||
|
||||
template <typename Kernel>
|
||||
bool is_any_edge_colinear(const CGAL::Polygon_2<Kernel>& pgn)
|
||||
{
|
||||
typedef typename CGAL::Point_2<Kernel> Point_2;
|
||||
typedef typename CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
typedef typename Polygon_2::Vertex_const_iterator Vertex_const_iterator;
|
||||
Vertex_const_iterator vci = pgn.vertices_begin();
|
||||
Point_2 firstVar = *(vci++);
|
||||
Point_2 secondVar = *(vci++);
|
||||
Point_2 thirdVar = *(vci++);
|
||||
for (; vci != pgn.vertices_end(); ++vci) {
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *vci;
|
||||
if (CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
}
|
||||
vci = pgn.vertices_begin();
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *(vci++);
|
||||
if(CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
|
||||
firstVar = secondVar;
|
||||
secondVar = thirdVar;
|
||||
thirdVar = *(vci++);
|
||||
if (CGAL::collinear(firstVar, secondVar, thirdVar)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \fn OutputIterator find_single_mold_translational_casting_2(const CGAL::Polygon_2<Kernel>& pgn, OutputIterator oi)
|
||||
* \param[in] pgn the input polygon that we want to check if is castable or not.
|
||||
* \param[in,out] oi the output iterator to put the top edges in
|
||||
* \param[in] kernel the kernel to use.
|
||||
* \return all the possible top edges of the polygon and there pullout direction
|
||||
* a pair of Directions is build this way [firstClockwise,secondClockwise]
|
||||
* (with no rotation)
|
||||
*/
|
||||
template <typename Kernel, typename OutputIterator>
|
||||
|
|
@ -109,20 +64,20 @@ top_edges_single_mold_translational_casting_2
|
|||
* point and the second point. (each of its sides might be open or closed)
|
||||
*/
|
||||
CGAL_precondition(pgn.is_simple());
|
||||
CGAL_precondition(!is_any_edge_colinear(pgn));
|
||||
CGAL_precondition(!internal::is_any_edge_colinear(pgn));
|
||||
|
||||
auto e_it = pgn.edges_begin();
|
||||
size_t edge_index = 0;
|
||||
CGAL::Orientation poly_orientation = pgn.orientation();
|
||||
auto segment_outer_circle =
|
||||
get_segment_outer_circle<Kernel>(*e_it++, poly_orientation);
|
||||
internal::get_segment_outer_circle<Kernel>(*e_it++, poly_orientation);
|
||||
internal::Circle_arrangment<Kernel> circle_arrangment(kernel,
|
||||
segment_outer_circle);
|
||||
|
||||
++edge_index;
|
||||
for (; e_it != pgn.edges_end(); ++e_it, ++edge_index) {
|
||||
segment_outer_circle =
|
||||
get_segment_outer_circle<Kernel>(*e_it, poly_orientation);
|
||||
internal::get_segment_outer_circle<Kernel>(*e_it, poly_orientation);
|
||||
circle_arrangment.add_segment_outer_circle(segment_outer_circle, edge_index);
|
||||
if (circle_arrangment.all_is_covered_twice()) return oi;
|
||||
}
|
||||
|
|
@ -134,6 +89,7 @@ top_edges_single_mold_translational_casting_2
|
|||
* \param[in] pgn the input polygon that we want to check if is castable or not.
|
||||
* \param[in,out] oi the output iterator to put the top edges in
|
||||
* \return all the possible top edges of the polygon and there pullout direction
|
||||
* a pair of Directions is build this way [firstClockwise,secondClockwise]
|
||||
* (with no rotation)
|
||||
*/
|
||||
template <typename Kernel, typename OutputIterator>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
#include <string>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <cctype>
|
||||
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_2.h>
|
||||
#include <CGAL/top_edges_single_mold_translational_casting_2.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Polygon_2<Kernel> Polygon_2;
|
||||
typedef Kernel::Direction_2 Direction_2;
|
||||
typedef Kernel::Point_2 Point_2;
|
||||
|
||||
typedef std::pair<Direction_2, Direction_2> Direction_range;
|
||||
typedef std::pair<size_t, Direction_range> Top_edge;
|
||||
|
||||
namespace SMS = CGAL::Set_movable_separability_2;
|
||||
|
||||
struct Top_edge_comparer {
|
||||
bool operator()(const Top_edge& a, const Top_edge& b)
|
||||
{
|
||||
auto facet_a = a.first;
|
||||
const auto& d1_a = a.second.first;
|
||||
const auto& d2_a = a.second.second;
|
||||
auto facet_b = b.first;
|
||||
const auto& d1_b = b.second.first;
|
||||
const auto& d2_b = b.second.second;
|
||||
|
||||
if (a.first < b.first) return true;
|
||||
if (a.first > b.first) return false;
|
||||
if (a.second.first < b.second.first) return true;
|
||||
if (a.second.first > b.second.first) return false;
|
||||
return a.second.second < b.second.second;
|
||||
}
|
||||
};
|
||||
|
||||
bool test_one_file(std::ifstream& inp)
|
||||
{
|
||||
Polygon_2 pgn;
|
||||
inp >> pgn;
|
||||
// std::cout << pgn << std::endl;
|
||||
|
||||
std::vector<Top_edge> top_edges;
|
||||
SMS::top_edges_single_mold_translational_casting_2(pgn, std::back_inserter(top_edges));
|
||||
|
||||
size_t exp_num_top_edges;
|
||||
inp >> exp_num_top_edges;
|
||||
// std::cout << "Exp. no. of top facets: " << exp_num_top_edges << std::endl;
|
||||
std::vector<Top_edge> exp_top_edges(exp_num_top_edges);
|
||||
for (auto& top_edge : exp_top_edges) {
|
||||
size_t facet;
|
||||
Direction_2 d1, d2;
|
||||
inp >> facet >> d1 >> d2;
|
||||
// std::cout << facet << " " << d1 << " " << d2 << std::endl;
|
||||
top_edge = std::make_pair(facet, std::make_pair(d1, d2));
|
||||
}
|
||||
|
||||
std::sort(top_edges.begin(), top_edges.end(), Top_edge_comparer());
|
||||
std::sort(exp_top_edges.begin(), exp_top_edges.end(), Top_edge_comparer());
|
||||
|
||||
if (top_edges.size() != exp_top_edges.size()) {
|
||||
std::cerr << "Number of facets: "
|
||||
<< "obtain: " << top_edges.size()
|
||||
<< ", expected: " << exp_top_edges.size()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
auto exp_it = exp_top_edges.begin();
|
||||
size_t i(0);
|
||||
for (auto it = top_edges.begin(); it != top_edges.end(); ++it, ++exp_it) {
|
||||
auto facet = it->first;
|
||||
const auto& d1 = it->second.first;
|
||||
const auto& d2 = it->second.second;
|
||||
auto exp_facet = exp_it->first;
|
||||
const auto& exp_d1 = exp_it->second.first;
|
||||
const auto& exp_d2 = exp_it->second.second;
|
||||
if ((facet != exp_facet) || (d1 != exp_d1) || (d2 != exp_d2)) {
|
||||
std::cerr << "Top edge[" << i++ << "]: "
|
||||
<< "obtained: " << facet << " " << d1 << " " << d2
|
||||
<< ", expected: " << exp_facet << " " << exp_d1 << " " << exp_d2
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
std::cerr << "Missing input file" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int success = 0;
|
||||
for (size_t i = 1; i < argc; ++i) {
|
||||
std::string str(argv[i]);
|
||||
if (str.empty()) continue;
|
||||
|
||||
auto itr = str.end();
|
||||
--itr;
|
||||
while (itr != str.begin()) {
|
||||
auto tmp = itr;
|
||||
--tmp;
|
||||
if (!isspace(*itr)) break;
|
||||
str.erase(itr);
|
||||
itr = tmp;
|
||||
}
|
||||
if (str.size() <= 1) continue;
|
||||
std::ifstream inp(str.c_str());
|
||||
if (!inp.is_open()) {
|
||||
std::cerr << "Failed to open " << str << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (! test_one_file(inp)) {
|
||||
std::cout << str << ": ERROR" << std::endl;
|
||||
++success;
|
||||
}
|
||||
else std::cout << str << ": succeeded" << std::endl;
|
||||
inp.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
Loading…
Reference in New Issue