Added drawing helpers for unbounded bisectors

This commit is contained in:
Fernando Cacciola 2010-07-27 15:51:36 +00:00
parent 348e36b3bf
commit c4ef2c709e
7 changed files with 183 additions and 65 deletions

View File

@ -27,7 +27,7 @@ int main()
SsPtr ss = CGAL::create_interior_straight_skeleton_2(input,lMaxTime);
dump_to_eps(input,*ss,"partial_skeleton.eps");
dump_ss_to_eps(input,ss,"partial_skeleton.eps");
return 0;

View File

@ -33,8 +33,7 @@ int main()
// Or you can pass the polygon directly, as below.
SsPtr oss = CGAL::create_exterior_straight_skeleton_2(poly);
dump_to_eps(poly,*iss,"interior_skeleton.eps");
dump_to_eps(poly,*oss,"exterior_skeleton.eps");
dump_ss_to_eps(poly,iss,oss,"straight_skeleton.eps");
return 0;
}

View File

@ -29,13 +29,13 @@ int main()
SsPtr ss0 = CGAL::create_straight_skeleton_2(poly, -1.5);
dump_to_eps(poly,*ss0,"uniform_weights_skeleton.eps");
dump_ss_to_eps(poly,ss0,"uniform_weights_skeleton.eps");
double weights[] = { -1.0, -1.0, -1.5, -1.0, -0.5, 1.0, 1.5, -1.0 } ;
SsPtr ss1 = CGAL::create_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end(), weights, weights+8);
dump_to_eps(poly,*ss1,"mixed_weights_skeleton.eps");
dump_ss_to_eps(poly,ss1,"mixed_weights_skeleton.eps");
return 0;
}

View File

@ -57,7 +57,7 @@ int main( int argc, char* argv[] )
if ( eps )
{
std::cerr << "Result: " << eps_name << std::endl ;
dump_to_eps(input,offset_polygons,eps);
dump_offset_to_eps(input,offset_polygons,eps);
}
else
{

View File

@ -39,8 +39,9 @@ int main( int argc, char* argv[] )
{
read_polygon_with_holes(is, input) ;
Straight_skeleton_ptr ss = CGAL::create_interior_straight_skeleton_2(input);
if ( ss )
Straight_skeleton_ptr inss = CGAL::create_interior_straight_skeleton_2(input);
Straight_skeleton_ptr outss = CGAL::create_exterior_straight_skeleton_2(input);
if ( inss && outss )
{
std::string eps_name ;
if ( argc > 2 )
@ -51,7 +52,7 @@ int main( int argc, char* argv[] )
if ( eps )
{
std::cerr << "Result: " << eps_name << std::endl ;
dump_to_eps(input,*ss,eps);
dump_ss_to_eps(input,inss,outss,eps);
}
else
{

View File

@ -25,8 +25,9 @@ Bbox_2 bbox_2 ( Polygon_with_holes_2<K> const& aPolyWH )
}
template<class InputIterator>
void dump_to_eps( InputIterator aBegin, InputIterator aEnd, char const* aType, double aScale, std::ostream& rOut )
void dump_poly_to_eps( InputIterator aBegin, InputIterator aEnd, char const* aType, double aScale, std::ostream& rOut )
{
InputIterator lLast = aEnd - 1 ;
@ -46,60 +47,84 @@ void dump_to_eps( InputIterator aBegin, InputIterator aEnd, char const* aType, d
}
}
template<class Poly>
void dump_to_eps( Poly const& aPoly, char const* aType, double aScale, std::ostream& rOut )
template<class K>
void dump_poly_to_eps( CGAL::Polygon_2<K> const& aPoly, char const* aType, double aScale, std::ostream& rOut )
{
dump_to_eps(aPoly.begin(), aPoly.end(), aType, aScale, rOut);
dump_poly_to_eps(aPoly.vertices_begin(), aPoly.vertices_end(), aType, aScale, rOut);
}
template<class K>
void dump_to_eps( CGAL::Polygon_2<K> const& aPoly, char const* aType, double aScale, std::ostream& rOut )
void dump_poly_to_eps( CGAL::Polygon_with_holes_2<K> const& aPWH, char const* aType, double aScale, std::ostream& rOut )
{
dump_to_eps(aPoly.vertices_begin(), aPoly.vertices_end(), aType, aScale, rOut);
}
template<class K>
void dump_to_eps( CGAL::Polygon_with_holes_2<K> const& aPWH, char const* aType, double aScale, std::ostream& rOut )
{
dump_to_eps(aPWH.outer_boundary(), aType, aScale, rOut ) ;
dump_poly_to_eps(aPWH.outer_boundary(), aType, aScale, rOut ) ;
for ( typename CGAL::Polygon_with_holes_2<K>::Hole_const_iterator hit = aPWH.holes_begin()
; hit != aPWH.holes_end()
; ++ hit
)
dump_to_eps(*hit, aType, aScale, rOut ) ;
dump_poly_to_eps(*hit, aType, aScale, rOut ) ;
}
template<class K>
void dump_to_eps( CGAL::Straight_skeleton_2<K> const& aSkeleton, char const* aType, double aScale, std::ostream& rOut )
void dump_ss_to_eps( CGAL::Straight_skeleton_2<K> const& aSkeleton, char const* aType, double aScale, std::ostream& rOut )
{
typedef typename CGAL::Straight_skeleton_2<K>::Halfedge_const_iterator Halfedge_const_iterator ;
typedef typename CGAL::Straight_skeleton_2<K>::Halfedge_const_handle Halfedge_const_handle ;
typedef typename CGAL::Straight_skeleton_2<K>::Traits Traits ;
typedef typename Traits::Point_2 Point_2 ;
typedef typename Traits::Vector_2 Vector_2 ;
typedef typename Traits::Segment_2 Segment_2 ;
for(Halfedge_const_iterator hit = aSkeleton.halfedges_begin(); hit != aSkeleton.halfedges_end(); ++hit)
{
Halfedge_const_handle h = hit ;
if( h->is_bisector() && ((h->id()%2)==0) && !h->has_infinite_time() && !h->opposite()->has_infinite_time() )
if( h->is_bisector() && ((h->id()%2)==0) )
{
rOut << aType << std::endl
<< aScale * h->vertex()->point().x()
Point_2 s,t;
if ( !h->has_infinite_time() && !h->opposite()->has_infinite_time() )
{
s = h->vertex()->point() ;
t = h->opposite()->vertex()->point();
}
else
{
Halfedge_const_handle outh = h->has_infinite_time() ? h : h->opposite();
Halfedge_const_handle contour_edge_0 = outh ->defining_contour_edge();
Halfedge_const_handle contour_edge_1 = outh->opposite()->defining_contour_edge();
Point_2 const& p0 = contour_edge_0->opposite()->vertex()->point();
Point_2 const& p1 = contour_edge_0 ->vertex()->point();
Point_2 const& p2 = contour_edge_1 ->vertex()->point();
Vector_2 bisect = CGAL::CGAL_SS_i::ccw_angular_bisector_2(p0, p1, p2);
s = p1 ;
t = p1 - ( h->weight() > 0 ? bisect : - bisect ) ;
}
rOut << aType
<< std::endl
<< aScale * CGAL::to_double(s.x())
<< " "
<< aScale * h->vertex()->point().y()
<< " "
<< aScale * h->opposite()->vertex()->point().x()
<< " "
<< aScale * h->opposite()->vertex()->point().y()
<< aScale * CGAL::to_double(s.y())
<< " "
<< aScale * CGAL::to_double(t.x())
<< " "
<< aScale * CGAL::to_double(t.y())
<< " E\n";
}
}
}
template<class Poly>
void dump_to_eps ( Poly const& aInput
, std::vector< boost::shared_ptr<Poly> > const& aOutput
, std::ostream& rOut
)
void dump_offset_to_eps( Poly const& aInput
, std::vector< boost::shared_ptr<Poly> > const& aOutput
, std::ostream& rOut
)
{
typedef std::vector< boost::shared_ptr<Poly> > Poly_vector ;
@ -108,19 +133,32 @@ void dump_to_eps ( Poly const& aInput
for( typename Poly_vector::const_iterator it = aOutput.begin() ; it != aOutput.end(); ++ it )
lBbox = lBbox + CGAL::bbox_2(**it);
double lScale = 1000 / (lBbox.xmax() - lBbox.xmin()) ;
double lWidth = (lBbox.xmax() - lBbox.xmin()) ;
double lHeight = (lBbox.ymax() - lBbox.ymin()) ;
double lSize = (std::max)(lWidth, lHeight);
double lScale = 1000 / lSize ;
double lMargin = lSize * 0.05 ;
if ( lScale < 1 )
lScale = 1 ;
CGAL::Bbox_2 lViewport(std::floor(lScale * (lBbox.xmin() - lMargin) )
,std::floor(lScale * (lBbox.ymin() - lMargin) )
,std::ceil (lScale * (lBbox.xmax() + lMargin) )
,std::ceil (lScale * (lBbox.ymax() + lMargin) )
);
rOut << "%!PS-Adobe-2.0 EPSF-2.0\n%%BoundingBox:"
<< static_cast<int>(std::floor(lScale* lBbox.xmin()-1))
<< static_cast<int>(lViewport.xmin())
<< " "
<< static_cast<int>(std::floor(lScale* lBbox.ymin()-1))
<< static_cast<int>(lViewport.ymin())
<< " "
<< static_cast<int>(std::ceil(lScale*lBbox.xmax()+1))
<< static_cast<int>(lViewport.xmax())
<< " "
<< static_cast<int>(std::ceil(lScale*lBbox.ymax()+1))
<< static_cast<int>(lViewport.ymax())
<< std::endl;
rOut << "%%EndComments\n"
@ -133,36 +171,50 @@ void dump_to_eps ( Poly const& aInput
"% stroke - x1 y1 x2 y2 E\n"
"/E {newpath moveto lineto stroke} bind def\n\n" ;
dump_to_eps(aInput,"input",lScale,rOut);
dump_poly_to_eps(aInput,"input",lScale,rOut);
for( typename Poly_vector::const_iterator it = aOutput.begin() ; it != aOutput.end(); ++ it )
dump_to_eps(**it,"output",lScale,rOut);
dump_poly_to_eps(**it,"output",lScale,rOut);
rOut << "grestore\nshowpage" << std::endl;
}
template<class Input, class K>
void dump_to_eps ( Input const& aInput
, CGAL::Straight_skeleton_2<K> const& aSkeleton
, std::ostream& rOut
)
void dump_ss_to_eps ( Input const& aInput
, boost::shared_ptr< CGAL::Straight_skeleton_2<K> > const& aInSkeleton
, boost::shared_ptr< CGAL::Straight_skeleton_2<K> > const& aOutSkeleton
, std::ostream& rOut
)
{
CGAL::Bbox_2 lBbox = CGAL::bbox_2(aInput);
double lScale = 1000 / (lBbox.xmax() - lBbox.xmin()) ;
double lWidth = (lBbox.xmax() - lBbox.xmin()) ;
double lHeight = (lBbox.ymax() - lBbox.ymin()) ;
double lSize = (std::max)(lWidth, lHeight);
double lScale = 1000 / lSize ;
double lMargin = lSize * 0.25 ;
if ( lScale < 1 )
lScale = 1 ;
CGAL::Bbox_2 lViewport(std::floor(lScale * (lBbox.xmin() - lMargin) )
,std::floor(lScale * (lBbox.ymin() - lMargin) )
,std::ceil (lScale * (lBbox.xmax() + lMargin) )
,std::ceil (lScale * (lBbox.ymax() + lMargin) )
);
rOut << "%!PS-Adobe-2.0 EPSF-2.0\n%%BoundingBox:"
<< static_cast<int>(std::floor(lScale* lBbox.xmin()-1))
<< static_cast<int>(lViewport.xmin())
<< " "
<< static_cast<int>(std::floor(lScale* lBbox.ymin()-1))
<< static_cast<int>(lViewport.ymin())
<< " "
<< static_cast<int>(std::ceil(lScale*lBbox.xmax()+1))
<< static_cast<int>(lViewport.xmax())
<< " "
<< static_cast<int>(std::ceil(lScale*lBbox.ymax()+1))
<< static_cast<int>(lViewport.ymax())
<< std::endl;
rOut << "%%EndComments\n"
@ -170,30 +222,37 @@ void dump_to_eps ( Input const& aInput
"1.0 setlinewidth\n"
"/input { 1 0 0 setrgbcolor } bind def\n"
"/input_w { 0.1 setlinewidth } bind def\n"
"/skeleton { 0 1 0 setrgbcolor } bind def\n"
"/skeleton_w { 0.1 setlinewidth } bind def\n"
"/in_skeleton { 0 1 0 setrgbcolor } bind def\n"
"/in_skeleton_w { 0.1 setlinewidth } bind def\n"
"/out_skeleton { 0 1 0 setrgbcolor } bind def\n"
"/out_skeleton_w { 0.1 setlinewidth } bind def\n"
"% stroke - x1 y1 x2 y2 E\n"
"/E {newpath moveto lineto stroke} bind def\n\n" ;
dump_to_eps(aInput,"input",lScale,rOut);
dump_poly_to_eps(aInput,"input",lScale,rOut);
dump_to_eps(aSkeleton,"skeleton",lScale,rOut);
if ( aInSkeleton )
dump_ss_to_eps(*aInSkeleton,"in_skeleton",lScale,rOut);
if ( aOutSkeleton )
dump_ss_to_eps(*aOutSkeleton,"out_skeleton",lScale,rOut);
rOut << "grestore\nshowpage" << std::endl;
}
template<class Input, class K>
void dump_to_eps ( Input const& aInput
, CGAL::Straight_skeleton_2<K> const& aSkeleton
, std::string aFilename
)
void dump_ss_to_eps ( Input const& aInput
, boost::shared_ptr< CGAL::Straight_skeleton_2<K> > const& aInSkeleton
, boost::shared_ptr< CGAL::Straight_skeleton_2<K> > const& aOutSkeleton
, std::string aFilename
)
{
std::ofstream eps(aFilename.c_str()) ;
if ( eps )
{
std::cerr << "Result: " << aFilename << std::endl ;
dump_to_eps(aInput,aSkeleton,eps);
dump_ss_to_eps(aInput,aInSkeleton,aOutSkeleton,eps);
}
else
{
@ -201,17 +260,26 @@ void dump_to_eps ( Input const& aInput
}
}
template<class Input, class K>
void dump_ss_to_eps ( Input const& aInput
, boost::shared_ptr< CGAL::Straight_skeleton_2<K> > const& aSkeleton
, std::string aFilename
)
{
dump_ss_to_eps(aInput, aSkeleton, boost::shared_ptr< CGAL::Straight_skeleton_2<K> >() , aFilename);
}
template<class Input, class Output>
void dump_to_eps ( Input const& aInput
, Output const& aOutput
, std::string aFilename
)
void dump_offset_to_eps ( Input const& aInput
, Output const& aOutput
, std::string aFilename
)
{
std::ofstream eps(aFilename.c_str()) ;
if ( eps )
{
std::cerr << "Result: " << aFilename << std::endl ;
dump_to_eps(aInput,aOutput,eps);
dump_offset_to_eps(aInput,aOutput,eps);
}
else
{

View File

@ -147,6 +147,56 @@ private:
Handle mE[3];
} ;
//
// The following functions are only for drawing of unbounded bisectors
//
template<class Vector_2>
inline double vector_angle_wrt_X_axis_2( Vector_2 const& v ) { return std::atan2( CGAL::to_double(v.y()), CGAL::to_double(v.x())); }
template<class Vector_2>
inline double ccw_angle_between_vectors_2( Vector_2 const& u, Vector_2 const& v )
{
double au = vector_angle_wrt_X_axis_2(u);
double av = vector_angle_wrt_X_axis_2(v);
double phi = av - au ;
if ( phi < 0)
phi = 2.0 * CGAL_PI + phi;
return phi ;
}
template<class Vector_2>
inline Vector_2 create_vector_rotated_2( Vector_2 const& u, double phi )
{
double cos = std::cos(phi);
double sin = std::sin(phi);
return Vector_2( u.x() * cos - u.y() * sin
, u.x() * sin + u.y() * cos
) ;
}
template<class Point_2>
typename CGAL::Kernel_traits<Point_2>::Kernel::Vector_2
ccw_angular_bisector_2( Point_2 const& p0, Point_2 const& p1, Point_2 const& p2 )
{
typedef typename CGAL::Kernel_traits<Point>::Kernel K ;
typedef typename K::Segment_2 Segment_2 ;
typedef typename K::Vector_2 Vector_2 ;
Vector_2 u = p2 - p1 ;
Vector_2 v = p0 - p1 ;
double sweep = ccw_angle_between_vectors_2(u ,v);
double phi = sweep * 0.5;
return create_vector_rotated_2(u, phi);
}
} // namespace CGAL_SS_i
enum Trisegment_collinearity