Skip to content
Snippets Groups Projects
Commit 689064da authored by Guillaume Damiand's avatar Guillaume Damiand
Browse files

Initial import of sources

parent e24ed805
No related branches found
No related tags found
No related merge requests found
Showing
with 7104 additions and 0 deletions
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_TYPEDEFS_H
#define CGAL_TYPEDEFS_H
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
#include <CGAL/Compact_container.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Timer.h>
#include <vector>
template<typename LCC>
class Inner_point;
///////////////////////////////////////////////////////////////////////////////
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK;
typedef EPECK::FT ECoord;
typedef EPECK::Point_2 EPoint;
typedef EPECK::Segment_2 ESegment;
typedef EPECK::Iso_rectangle_2 ERectangle;
typedef EPICK::FT ICoord;
typedef EPICK::Point_2 IPoint;
typedef EPICK::Segment_2 ISegment;
typedef EPICK::Iso_rectangle_2 IRectangle;
///////////////////////////////////////////////////////////////////////////////
// typedef CGAL::Timer My_timer;
typedef CGAL::Real_timer My_timer;
///////////////////////////////////////////////////////////////////////////////
template<typename Ref>
struct Info_for_face
{
using Face_attribute_handle=
typename Ref::template Attribute_handle<2>::type;
Info_for_face() : m_finite(true), m_father(nullptr)
{}
bool m_finite;
std::vector<Face_attribute_handle> m_son;
Face_attribute_handle m_father;
};
////////////////////////////////////////////////////////////////////////////////
template<typename Ref>
struct Info_for_vertex
{
using Dart_handle=typename Ref::Dart_handle;
Info_for_vertex(Dart_handle dh=nullptr) : m_dart_above(dh)
{}
Dart_handle m_dart_above;
};
////////////////////////////////////////////////////////////////////////////////
struct Myitem
{
template<class Ref>
struct Dart_wrapper
{
typedef CGAL::Cell_attribute_with_point<Ref, Info_for_vertex<Ref>> Vertex_attribute;
typedef CGAL::Cell_attribute<Ref, Info_for_face<Ref>> Face_attribute;
typedef std::tuple<Vertex_attribute,void,Face_attribute> Attributes;
};
};
typedef CGAL::Linear_cell_complex_traits
<2, CGAL::Exact_predicates_exact_constructions_kernel> Traits;
typedef CGAL::Linear_cell_complex_for_combinatorial_map
<2,2,Traits,Myitem,CGAL_ALLOCATOR(int),
CGAL::Combinatorial_map_base,
CGAL::CMap_linear_cell_complex_storage_1
<2, 2, Traits, Myitem, CGAL_ALLOCATOR(int), CGAL::Tag_true>
> LCC_2;
///////////////////////////////////////////////////////////////////////////////
typedef LCC_2::Dart_handle Dart_handle;
typedef LCC_2::Dart_const_handle Dart_const_handle;
///////////////////////////////////////////////////////////////////////////////
#endif // CGAL_TYPEDEFS_H
project(Parallel_arrangement)
cmake_minimum_required(VERSION 3.1)
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
cmake_policy(VERSION 2.8.4)
else()
cmake_policy(VERSION 2.6)
endif()
endif()
cmake_policy(SET CMP0064 NEW)
set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
if ( COMMAND cmake_policy )
cmake_policy( SET CMP0003 NEW )
endif()
# ADD_DEFINITIONS("-Wall -Wextra")
# ADD_DEFINITIONS("-O3")
# -fsanitize=thread
set(CMAKE_CXX_STANDARD 17)
find_package(Boost COMPONENTS system filesystem REQUIRED)
# ##########################################################
# Find some packages
find_package(CGAL COMPONENTS Qt5 REQUIRED) # CGAL and QT5 component
if(CGAL_Qt5_FOUND)
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()
# ##########################################################
## For profilling with gprof
# add_definitions("-pg")
# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
# add_definitions("-D_GLIBCXX_DEBUG")
add_definitions("-g") # for vtune (perf evaluator)
# ##########################################################
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/")
set(HEADER_FILES
CGAL_typedefs.h
draw_shds.h
Export_xfig.hh
Hds.h
memory.h
My_arr_segment_traits_2.h
My_construction_subcurve.h
My_event.h
My_surface_sweep.h
My_visitor.h
Partial_hds.h
SHds.h
SHds_to_lcc.h
SHds_to_cgal_arrangement.h
Segment_readers.h
Print_txt.h)
set(SOURCE_FILES
parallel-arrangement-bench.cpp
parallel-arrangement.cpp
compute-arrangement-streamed.cpp)
foreach(cppfile ${SOURCE_FILES})
create_single_source_cgal_program("${cppfile}" "${HEADER_FILES}")
endforeach()
# ##########################################################
# Link
if (CGAL_Qt5_FOUND)
target_link_libraries(parallel-arrangement PUBLIC CGAL::CGAL_Qt5)
endif()
find_package(TBB REQUIRED)
include(CGAL_TBB_support)
target_link_libraries(parallel-arrangement PUBLIC pthread CGAL::TBB_support ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY})
target_link_libraries(parallel-arrangement-bench PUBLIC pthread CGAL::TBB_support ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY})
target_link_libraries(compute-arrangement-streamed PUBLIC pthread CGAL::TBB_support ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY})
# ##########################################################
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef EXPORT_XFIG_H
#define EXPORT_XFIG_H
#include <cmath>
#include <string>
#include <fstream>
class Export_xfig
{
constexpr static unsigned int MAX_PROF=999; // max depth for xfig
public:
// xsize is the length of the bbox in x-coordinates
// We resize the scene so that the x-length is xfig_x_size.
Export_xfig(const std::string& filename, double xsize,
double xfig_x_size=20000.,
bool invert_y=false) :
m_nb_couls(0),
m_invert_y(invert_y),
m_x_factor(xfig_x_size/xsize),
m_x_shift(0),
m_y_shift(0)
{
m_ofstream.open(filename);
if (!m_ofstream)
{ std::cerr<<"ERROR opening "<<filename<<std::endl; }
sauveEntete();
}
~Export_xfig()
{ m_ofstream.close(); }
void set_x_shift(int x)
{ m_x_shift=x; }
void set_y_shift(int y)
{ m_y_shift=y; }
uint8_t add_color(const CGAL::Color& c)
{
m_ofstream<<std::setfill('0');
m_ofstream<<"0 "<<32+m_nb_couls<<" #"
<<std::hex<<std::uppercase<<std::setw(2)
<<static_cast<int>(c.red())
<<static_cast<int>(c.green())
<<static_cast<int>(c.blue())<<std::dec<<std::endl;
++m_nb_couls;
return m_nb_couls-1;
}
/* TODO void debutComposante( ofstream &os,
const CVertex & min, const CVertex & max )
{
m_ofstream<<"6 "
<<int(RINT(min.getX()+decalageX))<<" "
<<int(RINT(min.getY()+decalageY))<<" "
<<int(RINT(max.getX()+decalageX))<<" "
<<int(RINT(max.getY()+decalageY))<<endl;
}*/
// Fin d'une composante : m_ofstream<<"-6\n";
void point(double x, double y, uint16_t rayon,
u_int8_t coul, uint16_t larg, uint16_t prof)
{
m_ofstream<<"1 4 0 "<<static_cast<int>(larg)<<" "
<<static_cast<int>(32+coul)<<" "
<<static_cast<int>(32+coul)<<" "
<<static_cast<int>(prof);
m_ofstream <<" 0 20 0.000 1 0.0000 ";
m_ofstream<<point_to_string(x, y)<<" " // Centre x et y
<<static_cast<int>(rayon)<<" "<<static_cast<int>(rayon)<<" " //Rayon en x et en y
<<point_to_string(x, y)<<" " // Premier point == centre
<<point_to_string(x+rayon, y)<<" " // deuxieme point (sur le cercle)
<<std::endl;
}
void segment(double x1, double y1, double x2, double y2,
u_int8_t coul, uint16_t larg, bool arrow, uint16_t prof)
{
int ix1=p_to_x(x1);
int iy1=p_to_y(y1);
int ix2=p_to_x(x2);
int iy2=p_to_y(y2);
if (ix1!=ix2 || iy1!=iy2)
{
m_ofstream<<"2 1 0 "<<static_cast<int>(larg)<<" "
<<static_cast<int>(32+coul)<<" "
<<static_cast<int>(32+coul)<<" "
<<static_cast<int>(prof)
<<" 0 -1 0.000 1 0 7 ";
if (arrow)
{
m_ofstream<<"1 0 2\n"
<<" 2 0 1.00 60.00 120.00\n";
}
else
{ m_ofstream<<"0 0 2\n"; }
m_ofstream<<ix1<<" "<<iy1<<" "<<ix2<<" "<<iy2<<std::endl;
}
}
void rectangle(double x1, double y1, double x2, double y2,
u_int8_t coul, uint16_t larg, bool arrow, uint16_t prof)
{
segment(x1, y1, x2, y1, coul, larg, arrow, prof);
segment(x2, y1, x2, y2, coul, larg, arrow, prof);
segment(x2, y2, x1, y2, coul, larg, arrow, prof);
segment(x1, y2, x1, y1, coul, larg, arrow, prof);
}
protected:
int transfoMmPixel(double val) const
{
// Xfig est en 1200 dpi, et donc le nombre de pixel par mm vaut 1200/25.4
// (sachant que 1inch==25.4mm)
// double dpmX=(1200/25.4);
return std::round(val*m_x_factor); //(val*dpmX)/COEF_DE_REDUCTION);
}
int p_to_x(double val) const
{ return transfoMmPixel(val)+m_x_shift; }
int p_to_y(double val) const
{
int res=transfoMmPixel(val)+m_y_shift;
if (m_invert_y) { res=-res; }
return res;
}
std::string value_to_string(double val)
{ return std::to_string(transfoMmPixel(val)); }
std::string point_to_string(double x, double y)
{
int ix=p_to_x(x);
int iy=p_to_y(y);
return std::string(std::to_string(ix)+" "+std::to_string(iy));
}
void sauveEntete()
{
m_ofstream<<"#FIG 3.2"<<std::endl
<<"Portrait"<<std::endl
<<"Metric"<<std::endl
<<"A4"<<std::endl
<<"100.00"<<std::endl
<<"Single"<<std::endl
<<"-2"<<std::endl
<<"1200 2"<<std::endl;
}
/* void CControlerGMap::sauveFace(const std::vector<Point2d>& pts,
int coulFill, int larg, int AProf )
{
assert(pts.size()>=3); // 3 => polygone à 2 arêtes...
os<<"2 1 0 " << larg << " "
<< 32+COUL_DART << " " << 32+coulFill << " "
<< (1+AProf) <<" 0 20 0.000 1 0 7 0 0 "
<< nbPts << endl;
for (int i=0; i<nbPts; ++i)
{
os << int(RINT(p[i].getX()+decalageX)) << " "
<< int(RINT(p[i].getY()+decalageY)) << endl;
}
}
*/
protected:
std::ofstream m_ofstream;
uint8_t m_nb_couls;
bool m_invert_y;
double m_x_factor;
int m_x_shift, m_y_shift;
};
////////////////////////////////////////////////////////////////////////////////
#endif // EXPORT_XFIG_H
src/Hds.h 0 → 100644
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef HDS_H
#define HDS_H
#include <bitset>
#include "CGAL_typedefs.h"
#include "Print_txt.h"
#include "Export_xfig.hh"
///////////////////////////////////////////////////////////////////////////////
class Halfedge;
class Vertex;
class Face;
class HDS;
class SHds;
////////////////////////////////////////////////////////////////////////////////
typedef CGAL::Compact_container<Halfedge>::iterator Halfedge_handle;
typedef CGAL::Compact_container<Halfedge>::const_iterator Halfedge_const_handle;
typedef CGAL::Compact_container<Vertex>::iterator Vertex_handle;
typedef CGAL::Compact_container<Face>::iterator Face_handle;
////////////////////////////////////////////////////////////////////////////////
class Halfedge
{
public:
friend class HDS;
friend class Vertex;
friend class SHds;
typedef uint32_t size_type;
static const size_type NB_MARKS = 32;
Halfedge(Halfedge_handle opposite=nullptr,
Vertex_handle vertex=nullptr,
int edge_id=0) :
m_opposite(opposite),
m_prev_around_vertex(nullptr),
m_next_around_vertex(nullptr),
m_vertex(vertex),
m_face(nullptr),
m_edge_id(edge_id)
{}
void set( Halfedge_handle opposite,
Halfedge_handle prev_around_vertex,
Halfedge_handle next_around_vertex,
Vertex_handle vertex,
int edge_id)
{
m_opposite=opposite;
m_prev_around_vertex=prev_around_vertex;
m_next_around_vertex=next_around_vertex;
m_vertex=vertex;
m_edge_id=edge_id;
}
Halfedge_handle opposite() const
{ return m_opposite; }
Halfedge_handle prev_around_vertex() const
{ return m_prev_around_vertex; }
Halfedge_handle next_around_vertex() const
{ return m_next_around_vertex; }
Vertex_handle vertex() const
{ return m_vertex; }
Face_handle face() const
{ return m_face; }
int edge_id() const
{ return m_edge_id; }
bool get_mark(size_type amark) const
{
CGAL_assertion(amark>=0 && amark<NB_MARKS);
return m_marks[amark];
}
void set_mark(size_type amark, bool avalue) const
{
CGAL_assertion(amark>=0 && amark<NB_MARKS);
m_marks.set(amark, avalue);
}
void flip_mark(size_type amark) const
{
CGAL_assertion(amark>=0 && amark<NB_MARKS);
m_marks.flip(amark);
}
std::bitset<NB_MARKS> get_marks() const
{ return m_marks; }
void set_marks(const std::bitset<NB_MARKS>& amarks) const
{ m_marks=amarks; }
void* for_compact_container() const
{ return m_opposite.for_compact_container(); }
void for_compact_container(void* p)
{ m_opposite.for_compact_container(p);}
protected:
Halfedge_handle m_opposite;
Halfedge_handle m_prev_around_vertex;
Halfedge_handle m_next_around_vertex;
Vertex_handle m_vertex;
Face_handle m_face;
int m_edge_id; // >0 if halfedge from left to right or vertical and bottom to top, <0 otherwise
// two halfedges of the same edge have the same value and opposite sign
mutable std::bitset<NB_MARKS> m_marks;
};
////////////////////////////////////////////////////////////////////////////////
class Global_halfedge
{
public:
friend class SHds;
Global_halfedge(std::size_t strip_id=0,
Halfedge_handle hh=nullptr):
m_strip_id(strip_id),
m_hh(hh)
{}
void set(std::size_t strip_id=0, Halfedge_handle hh=nullptr)
{ m_strip_id=strip_id; m_hh=hh; }
void set_halfedge(Halfedge_handle hh)
{ m_hh=hh; }
std::size_t strip_id() const
{ return m_strip_id; }
const Halfedge_handle& halfedge() const
{ return m_hh; }
Halfedge_handle& halfedge()
{ return m_hh; }
void go_to_left_strip()
{ assert(m_strip_id>0); --m_strip_id; }
void go_to_right_strip()
{ ++m_strip_id; }
bool operator==(const Global_halfedge& other) const
{ return m_hh==other.m_hh; } // Handle are unique, thus we don't need to compare m_strip_id
bool operator!=(const Global_halfedge& other) const
{ return !operator==(other); }
bool operator<(const Global_halfedge& other) const
{ return m_strip_id<other.m_strip_id ||
(m_strip_id==other.m_strip_id && m_hh<other.m_hh); }
bool operator>(const Global_halfedge& other) const
{ return other.operator<(*this); }
bool operator>=(const Global_halfedge& other) const
{ return !operator<(other); }
bool operator<=(const Global_halfedge& other) const
{ return !operator>(other); }
protected:
std::size_t m_strip_id;
Halfedge_handle m_hh;
};
////////////////////////////////////////////////////////////////////////////////
class Vertex
{
public:
friend class HDS;
friend class Halfedge;
Vertex() :
m_first_halfedge(nullptr),
m_above_halfedge(nullptr)
{}
Vertex(const EPoint& p) :
m_point(p),
m_first_halfedge(nullptr),
m_above_halfedge(nullptr)
{}
void set(const EPoint& p, Halfedge_handle first_halfedge,
Halfedge_handle above_halfedge)
{
m_point=p;
m_first_halfedge=first_halfedge;
m_above_halfedge=above_halfedge;
}
const EPoint& point() const
{ return m_point; }
Halfedge_handle first_halfedge() const
{ return m_first_halfedge; }
Halfedge_handle above_halfedge() const
{ return m_above_halfedge; }
void set_above_halfedge(Halfedge_handle dh)
{ m_above_halfedge=dh; }
bool no_left_edge() const
{
return m_first_halfedge->m_edge_id>0; // If the first halfedge is from left to right
// or vertical and bottom to up, there is no left edge around the vertex
}
void serialize_point(std::ostream& os) const
{
CGAL::exact(m_point);
os<<std::setprecision(17)<<m_point;
}
void* for_compact_container() const
{ return m_first_halfedge.for_compact_container(); }
void for_compact_container(void* p)
{ m_first_halfedge.for_compact_container(p);}
protected:
EPoint m_point;
Halfedge_handle m_first_halfedge;
Halfedge_handle m_above_halfedge; // Halfedge handle of the edge above this vertex (nullptr if no such edge)
};
////////////////////////////////////////////////////////////////////////////////
class Face
{
public:
friend class HDS;
friend class Halfedge;
friend class SHds;
Face() :
m_strip_id(0),
m_first_halfedge(nullptr),
m_father(nullptr),
m_finite(true)
{}
void set(std::size_t strip_id,
Halfedge_handle first_halfedge,
Face_handle father,
bool finite)
{
m_strip_id=strip_id;
m_first_halfedge=first_halfedge;
m_father=father;
m_finite=finite;
}
std::size_t strip_id() const
{ return m_strip_id; }
Halfedge_handle first_halfedge() const
{ return m_first_halfedge; }
Face_handle father() const
{ return m_father; }
bool finite() const
{ return m_finite; }
const std::vector<Face_handle>& sons() const
{ return m_son; }
void* for_compact_container() const
{ return m_first_halfedge.for_compact_container(); }
void for_compact_container(void* p)
{ m_first_halfedge.for_compact_container(p);}
protected:
std::size_t m_strip_id; // strip id of the first halfedge
Halfedge_handle m_first_halfedge;
Face_handle m_father;
std::vector<Face_handle> m_son;
bool m_finite;
};
////////////////////////////////////////////////////////////////////////////////
class HDS
{
public:
typedef uint32_t size_type;
typedef CGAL::Compact_container<Halfedge> Halfedges_container;
typedef CGAL::Compact_container<Vertex> Vertices_container;
void clear()
{
m_halfedges.clear();
m_vertices.clear();
}
std::size_t number_of_halfedges() const
{ return m_halfedges.size(); }
std::size_t number_of_vertices() const
{ return m_vertices.size(); }
Halfedges_container& halfedges()
{ return m_halfedges; }
Vertices_container& vertices()
{ return m_vertices; }
const Halfedges_container& halfedges() const
{ return m_halfedges; }
const Vertices_container& vertices() const
{ return m_vertices; }
Halfedge_handle opposite(Halfedge_handle hh) const
{ return hh->m_opposite; }
Halfedge_handle prev_around_vertex(Halfedge_handle hh) const
{ return hh->m_prev_around_vertex; }
Halfedge_handle next_around_vertex(Halfedge_handle hh) const
{ return hh->m_next_around_vertex; }
Vertex_handle vertex(Halfedge_handle hh) const
{ return hh->m_vertex; }
Face_handle face(Halfedge_handle hh) const
{ return hh->m_face; }
const EPoint& point(Vertex_handle vh) const
{ return vh->point(); }
const EPoint& point(Halfedge_handle hh) const
{ return point(vertex(hh)); }
int edge_id(Halfedge_handle hh) const
{ return hh->m_edge_id; }
void move_to_opposite(Halfedge_handle& hh) const
{ hh=opposite(hh); }
void move_to_prev_around_vertex(Halfedge_handle& hh) const
{ hh=prev_around_vertex(hh); }
void move_to_next_around_vertex(Halfedge_handle& hh) const
{ hh=next_around_vertex(hh); }
// @return true iff halfedge hh is from left to right
// (or vertical and from bottom to top)
bool left_to_right(Halfedge_handle hh) const
{ return edge_id(hh)>0; }
// @return true iff halfedge hh is from right to left
bool right_to_left(Halfedge_handle hh) const
{ return edge_id(hh)<0; }
Vertex_handle create_vertex(const EPoint& p)
{ return m_vertices.emplace(p); }
void set_vertex(Halfedge_handle hh, Vertex_handle vh)
{ hh->m_vertex=vh; }
void set_vertex(Halfedge_handle hh, const EPoint& p)
{ set_vertex(hh, create_vertex(p)); }
Halfedge_handle create_edge(Vertex_handle vh, int segmentid)
{
assert(segmentid>0);
Halfedge_handle hh1=m_halfedges.emplace(nullptr, vh, segmentid);
Halfedge_handle hh2=m_halfedges.emplace(hh1, nullptr, -segmentid);
hh1->m_opposite=hh2;
return hh1;
}
void erase_halfedge(Halfedge_handle hh)
{ m_halfedges.erase(hh); }
void erase_edge(Halfedge_handle hh)
{
erase_halfedge(hh->m_opposite);
erase_halfedge(hh);
}
Halfedge_handle add_segment_around_vertex(Halfedge_handle hh,
Vertex_handle vh,
Halfedge_handle prevhh)
{
if (prevhh==nullptr)
{
assert(vh->first_halfedge()==nullptr);
vh->m_first_halfedge=hh;
}
else
{
assert(vh->first_halfedge()!=nullptr);
prevhh->m_next_around_vertex=hh;
hh->m_prev_around_vertex=prevhh;
}
return hh;
}
void end_of_vertex(Vertex_handle vh, Halfedge_handle prevhh)
{
assert(vh->first_halfedge()!=nullptr);
{
prevhh->m_next_around_vertex=vh->first_halfedge();
vh->first_halfedge()->m_prev_around_vertex=prevhh;
}
}
friend std::ostream& operator<<(std::ostream& os,
const HDS& hds)
{
os<<hds.halfedges().size()<<" "<<hds.vertices().size()<<std::endl;
for (auto it=hds.vertices().begin(), itend=hds.vertices().end(); it!=itend; ++it)
{
assert(it->first_halfedge()!=nullptr);
it->serialize_point(os);
os<<" "<<hds.halfedges().index(it->first_halfedge())
<<" "<<(it->above_halfedge()==nullptr?'-':'+');
if (it->above_halfedge()!=nullptr)
{ os<<" "<<hds.halfedges().index(it->above_halfedge()); }
os<<std::endl;
}
os<<std::endl;
for (auto it=hds.halfedges().begin(), itend=hds.halfedges().end(); it!=itend; ++it)
{
assert(it->opposite()!=nullptr);
assert(it->vertex()==nullptr || it->prev_around_vertex()!=nullptr);
assert(it->vertex()==nullptr || it->next_around_vertex()!=nullptr);
os<<" "<<hds.halfedges().index(it->opposite())
<<" "<<(it->vertex()!=nullptr?'+':'-');
if (it->vertex()!=nullptr)
{
os<<" "<<hds.halfedges().index(it->prev_around_vertex())
<<" "<<hds.halfedges().index(it->next_around_vertex())
<<" "<<hds.vertices().index(it->vertex());
}
os<<" "<<it->edge_id()<<std::endl;
}
return os;
}
void load(std::istream& is,
std::vector<Halfedge_handle>& halfedges,
std::vector<Vertex_handle>& vertices)
{
clear();
halfedges.clear();
vertices.clear();
std::size_t nb_halfedges, nb_vertices;
is>>nb_halfedges>>nb_vertices;
halfedges.reserve(nb_halfedges);
vertices.reserve(nb_vertices);
for (std::size_t i=0; i<nb_vertices; ++i)
{ vertices.push_back(m_vertices.emplace()); }
for (std::size_t i=0; i<nb_halfedges; ++i)
{ halfedges.push_back(m_halfedges.emplace()); }
EPoint p;
std::size_t ind1, ind2, ind3, ind4;
int int1;
char c;
for (std::size_t i=0; i<nb_vertices; ++i)
{
is>>p>>ind1>>c;
if (c=='+') is>>ind2;
vertices[i]->set(p, halfedges[ind1], (c=='+'?halfedges[ind2]:nullptr));
}
for (std::size_t i=0; i<nb_halfedges; ++i)
{
is>>ind1>>c;
if (c=='+') is>>ind2>>ind3>>ind4;
is>>int1;
halfedges[i]->set(halfedges[ind1],
(c=='+'?halfedges[ind2]:nullptr),
(c=='+'?halfedges[ind3]:nullptr),
(c=='+'?vertices[ind4]:nullptr), int1);
}
}
friend std::istream& operator>>(std::istream& is, HDS& hds)
{
std::vector<Halfedge_handle> halfedges;
std::vector<Vertex_handle> vertices;
hds.load(is, halfedges, vertices);
return is;
}
void export_to_xfig(Export_xfig& export_xfig,
double dx, double dy,
uint8_t coul_segments,
uint8_t coul_disks,
uint16_t width_segments,
uint16_t radius_disks) const
{
if (width_segments>0)
{
for (auto it=halfedges().begin(), itend=halfedges().end(); it!=itend; ++it)
{
if (it->vertex()!=nullptr && it->opposite()->vertex()!=nullptr &&
it<it->opposite())
{
export_xfig.segment(CGAL::to_double(it->vertex()->point().x())+dx,
CGAL::to_double(it->vertex()->point().y())+dy,
CGAL::to_double(it->opposite()->vertex()->point().x())+dx,
CGAL::to_double(it->opposite()->vertex()->point().y())+dy,
coul_segments, width_segments, false, 90);
}
}
}
if (radius_disks>0)
{
for (auto it=vertices().begin(), itend=vertices().end(); it!=itend; ++it)
{
export_xfig.point(CGAL::to_double(it->point().x())+dx,
CGAL::to_double(it->point().y())+dy,
radius_disks, coul_disks, false, 70);
}
}
}
protected:
CGAL::Compact_container<Halfedge> m_halfedges;
CGAL::Compact_container<Vertex> m_vertices;
};
////////////////////////////////////////////////////////////////////////////////
#endif // HDS_H
This diff is collapsed.
// Copyright (c) 2006,2007,2009,2010,2011 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Tali Zvi <talizvi@post.tau.ac.il>
// Baruch Zukerman <baruchzu@post.tau.ac.il>
#ifndef MY_CONSTRUCTION_SUBCURVE_H
#define MY_CONSTRUCTION_SUBCURVE_H
/*! \file
*
* Definition of the Arr_construction_subcurve class-template, which is an
* extended curve type, referred to as Subcurve, used by the surface-sweep
* framework.
*
* The surface-sweep framework is implemented as a template that is
* parameterized, among the other, by the Subcurve and Event types. That is,
* instance types of Subcurve and Event must be available when the
* surface-sweep template is instantiated.
*
* Arr_construction_subcurve derives from an instance of the Default_subcurve
* class template. The user is allowed to introduce new types that derive from
* an instance of the Arr_construction_subcurve class template. However, some of
* the fields of this template depends on the Subcurve type. We use the
* curiously recurring template pattern (CRTP) idiom to force the correct
* matching of these types.
*/
#include <CGAL/Surface_sweep_2/Default_subcurve.h>
#include <CGAL/Default.h>
#include "Hds.h"
namespace Ss2 = CGAL::Surface_sweep_2;
/*! \class Arr_construction_subcurve_base
*
* This is the base class of the Arr_construction_subcurve class template used
* by the (CRTP) idiom.
* \tparam GeometryTraits_2 the geometry traits.
* \tparam Event_ the event type.
* \tparam Allocator_ a type of an element that is used to acquire/release
* memory for elements of the event queue and the status
* structure, and to construct/destroy the elements in that
* memory. The type must meet the requirements of Allocator.
* \tparam Subcurve_ the subcurve actual type.
*
* The information contained in this class last:
* - ishe event that was handled on the curve.
* - The index for a subcurve that may represent a hole
* - Indices of all halfedge below the curve that may represent a hole.
*/
template <typename GeometryTraits_2, typename Event_, typename Allocator_,
typename Subcurve_>
class My_construction_subcurve_base :
public CGAL::Surface_sweep_2::Default_subcurve_base<GeometryTraits_2, Event_, Allocator_, Subcurve_>
{
public:
typedef GeometryTraits_2 Geometry_traits_2;
typedef Subcurve_ Subcurve;
typedef Event_ Event;
typedef Allocator_ Allocator;
private:
typedef Geometry_traits_2 Gt2;
typedef CGAL::Surface_sweep_2::Default_subcurve_base<Gt2, Event, Allocator, Subcurve>
Base;
public:
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
typedef Event* Event_ptr;
/*! Construct default. */
My_construction_subcurve_base() :
Base(),
m_last_event(nullptr),
m_original_segment_id(std::numeric_limits<int>::max()),
m_hh(nullptr)
{}
/*! Constructor from an x-monotone curve. */
My_construction_subcurve_base(X_monotone_curve_2& curve) :
Base(curve),
m_last_event(nullptr),
m_original_segment_id(curve.original_segment_id()),
m_hh(nullptr)
{}
protected:
Event_ptr m_last_event; // The last event that was handled on the curve.
int m_original_segment_id;
Halfedge_handle m_hh; // Halfedge_handle of the edge between m_last_event, and lying
// on this curve
public:
/*! Initialize the curve. */
void init(const X_monotone_curve_2& curve)
{
Base::init(curve);
m_original_segment_id=curve.original_segment_id();
}
/*! Set the event associated with the left end of the subcurve. */
template <typename SweepEvent>
void set_left_event(SweepEvent* left)
{
Base::set_left_event(left);
set_last_event(left);
}
/*! Set the last event on the subcurve. */
void set_last_event(Event_ptr e) { m_last_event = e; }
/*! Obtain the last event. */
Event_ptr last_event() const { return m_last_event; }
int original_segment_id() const
{ return m_original_segment_id; }
void set_original_segment_id(int id)
{ m_original_segment_id=id; }
Halfedge_handle halfedge() const
{ return m_hh; }
void set_halfedge(Halfedge_handle hh)
{ m_hh=hh; }
};
/*! \class Arr_construction_subcurve
*
* This class that holds information about a curve that is added to the
* arrangement. In addition to the information that is contained in
* Surface_sweep_subcurve, when an arrangement is constructed, a pointer to the
* last handled event on the curve is stored (in the base class). This
* information is used to retrieve hints when a subcurve of this curve is
* inserted into the planar map.
*
* Inherits from `Surface_sweep_subcurve`
* \sa `Surface_sweep_subcurve`
*/
template <typename GeometryTraits_2, typename Event_,
typename Allocator_ = CGAL_ALLOCATOR(int),
typename Subcurve_ = CGAL::Default>
class My_construction_subcurve :
public My_construction_subcurve_base<
GeometryTraits_2, Event_, Allocator_,
typename CGAL::Default::Get<Subcurve_,
My_construction_subcurve<GeometryTraits_2, Event_,
Allocator_,
Subcurve_> >::type>
{
public:
typedef GeometryTraits_2 Geometry_traits_2;
typedef Event_ Event;
typedef Allocator_ Allocator;
private:
typedef Geometry_traits_2 Gt2;
typedef My_construction_subcurve<Gt2, Event, Allocator,
Subcurve_> Self;
typedef typename CGAL::Default::Get<Subcurve_, Self>::type Subcurve;
typedef My_construction_subcurve_base<Gt2, Event, Allocator,
Subcurve> Base;
public:
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
typedef typename Base::Event_ptr Event_ptr;
/*! Construct deafult. */
My_construction_subcurve() {}
/*! Constructor from an x-monotone curve. */
My_construction_subcurve(X_monotone_curve_2& curve) :
Base(curve)
{}
};
#endif
// Copyright (c) 2006,2007,2009,2010,2011 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Tali Zvi <talizvi@post.tau.ac.il>
// Baruch Zukerman <baruchzu@post.tau.ac.il>
// Efi Fogel <efif@post.tau.ac.il>
#ifndef CGAL_MY_EVENT_H
#define CGAL_MY_EVENT_H
/*! \file
*
* Definition of the Arr_construction_event_base class-template.
*/
#include <vector>
#include <CGAL/Surface_sweep_2/Default_event_base.h>
#include <CGAL/assertions.h>
#include "Hds.h"
#include "My_construction_subcurve.h"
/*! \class Arr_construction_event_base
*
* This template represents an event used by the surface-sweep framework. It
* inherits either from `Default_event_base` (the default) or
* 'No_overlap_event_base' depending on whether the curve may overlap or not.
* It stores the data associated with an event in addition to the information
* stored in its base class. When constructing an arrangement, additional
* information is stored, in order to expedite the insertion of curves into the
* arrangement.
*
* The additional infomation contains the following:
* - among the left curves of the event, we keep the highest halfedge that
* was inserted into the arrangement at any given time and when there are no
* left curves, we keep the highest halfedge that was inseted to the right.
*
* \tparam GeometryTraits_2 the geometry traits.
* \tparam Allocator_ a type of an element that is used to acquire/release
* memory for elements of the event queue and the status
* structure, and to construct/destroy the elements in that
* memory. The type must meet the requirements of Allocator.
* \tparam SurfaceSweepEvent a template, an instance of which is used as the
* base class.
*
* \sa `Default_event_base`
* \sa `No_overlap_event_base`
*/
template <typename GeometryTraits_2, typename Subcurve_,
template <typename, typename>
class SurfaceSweepEvent = CGAL::Surface_sweep_2::Default_event_base>
class My_event_base :
public SurfaceSweepEvent<GeometryTraits_2, Subcurve_>
{
public:
typedef GeometryTraits_2 Geometry_traits_2;
typedef Subcurve_ Subcurve;
private:
typedef Geometry_traits_2 Gt2;
typedef SurfaceSweepEvent<Gt2, Subcurve> Base;
typedef My_event_base<Gt2, Subcurve, SurfaceSweepEvent> Self;
public:
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
typedef typename Gt2::Point_2 Point_2;
typedef typename Base::Subcurve_container Subcurve_container;
typedef typename Base::Subcurve_iterator Subcurve_iterator;
typedef typename Base::Subcurve_reverse_iterator Subcurve_reverse_iterator;
protected:
Vertex_handle m_vertex; // The vertex handle associated with this event.
Halfedge_handle m_above_halfedge; // The halfedge handle of the subcurve just above this event.
bool m_before_strip;
public:
/*! Default constructor. */
My_event_base(): m_vertex(nullptr), m_above_halfedge(nullptr), m_before_strip(false)
{}
/*! Destructor */
~My_event_base() {}
/*! Set the vertex handle. */
void set_vertex_handle(Vertex_handle vh) { m_vertex=vh; }
/*! Get the vertex handle. */
Vertex_handle vertex_handle() const { return m_vertex; }
void set_above_halfedge(Halfedge_handle hh)
{ m_above_halfedge=hh; }
Halfedge_handle above_halfedge() const
{ return m_above_halfedge; }
bool before_strip() const
{ return m_before_strip; }
void set_before_strip()
{ m_before_strip=true; }
};
template <typename GeometryTraits_2,
typename Allocator_ = CGAL_ALLOCATOR(int)>
class My_event :
public My_event_base<GeometryTraits_2,
My_construction_subcurve<GeometryTraits_2,
My_event<GeometryTraits_2, Allocator_>,
Allocator_> >
{
public:
/*! Construct default. */
My_event() {}
};
#endif
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef MY_SURFACE_SWEEP_H
#define MY_SURFACE_SWEEP_H
#include <CGAL/Surface_sweep_2.h>
template <typename Visitor_>
class My_surface_sweep_2:
CGAL::Surface_sweep_2::Surface_sweep_2<Visitor_>
{
public:
typedef My_surface_sweep_2<Visitor_> Self;
using Base=CGAL::Surface_sweep_2::Surface_sweep_2<Visitor_>;
using Geometry_traits_2=typename Base::Geometry_traits_2;
using Point_2=typename Base::Point_2;
using Event_queue_iterator=typename Base::Event_queue_iterator;
using Event_subcurve_iterator=typename Base::Event_subcurve_iterator;
using Subcurve=typename Base::Subcurve;
My_surface_sweep_2(Visitor_* visitor) : Base(visitor) {}
My_surface_sweep_2(const Geometry_traits_2* traits, Visitor_* visitor) :
Base(traits, visitor) {}
template <typename CurveInputIterator>
void sweep_until(CurveInputIterator curves_begin,
CurveInputIterator curves_end,
const Point_2& p)
{
this->m_visitor->before_sweep();
this->_init_sweep(curves_begin, curves_end);
//m_visitor->after_init();
this->_sweep_until(p);
this->_complete_sweep();
this->m_visitor->after_sweep();
}
protected:
void _sweep_until(const Point_2& p)
{
// Looping over the events in the queue.
Event_queue_iterator eventIter = this->m_queue->begin();
std::size_t number_of_strips=this->m_visitor->number_of_strips();
std::size_t strip_id=this->m_visitor->strip_id();
bool before_strip=true;
bool after_strip=false;
if (strip_id==0)
{
before_strip=false;
this->m_visitor->enter_in_strip();
}
while (eventIter != this->m_queue->end()) {
// Get the next event from the queue.
this->m_currentEvent = *eventIter;
if (number_of_strips>1)
{
if (before_strip)
{
before_strip=(CGAL::compare_x(this->m_currentEvent->point(),
this->m_visitor->pmin())==CGAL::SMALLER);
if (!before_strip)
{ this->m_visitor->enter_in_strip(); }
}
if (!after_strip && strip_id<number_of_strips-1)
{
after_strip=(CGAL::compare_x(this->m_currentEvent->point(),
this->m_visitor->pmax())!=CGAL::SMALLER);
if (after_strip) { this->m_visitor->end_of_strip(); }
}
}
if (!after_strip)
{
this->_handle_left_curves();
this->_handle_right_curves();
}
if (this->m_visitor->after_handle_event(this->m_currentEvent,
this->m_status_line_insert_hint,
this->m_is_event_on_above))
{
this->deallocate_event(this->m_currentEvent);
}
this->m_queue->erase(eventIter);
eventIter = this->m_queue->begin();
}
this->m_statusLine.clear();
}
};
#endif // MY_SURFACE_SWEEP_H
// Copyright (c) 2005,2006,2007,2009,2010,2011 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s): Baruch Zukerman <baruchzu@post.tau.ac.il>
// Efi Fogel <efif@post.tau.ac.il>
// (based on old version by Tali Zvi)
#ifndef CGAL_MY_VISITOR_H
#define CGAL_MY_VISITOR_H
/*! \file
*
* Definition of a surface-sweep visitor that reports all maximal x-monotone
* non-intersecting x-monotone curves induced by a set of input curves.
*/
#include <vector>
#include <CGAL/Surface_sweep_2/Default_visitor.h>
#include <CGAL/Surface_sweep_2/Surface_sweep_2_utils.h>
#include "Hds.h"
#include "My_surface_sweep.h"
#include "My_event.h"
#include "My_construction_subcurve.h"
#include "Partial_hds.h"
/*! \class Subcurves_visitor
*
* A simple sweep-line visitor that reports all maximal x-monotone
* non-intersecting x-monotone curves induced by a set of input curves. Used by
* compute_subcurves().
*/
template <typename GeometryTraits_2,
typename Allocator_ = CGAL_ALLOCATOR(int)>
class My_visitor :
public CGAL::Surface_sweep_2::Default_visitor
<My_visitor<GeometryTraits_2, Allocator_>,
GeometryTraits_2,
Allocator_,
My_event<GeometryTraits_2, Allocator_>,
My_construction_subcurve<GeometryTraits_2,
My_event<GeometryTraits_2, Allocator_>,
Allocator_>
>
{
public:
typedef GeometryTraits_2 Geometry_traits_2;
typedef Allocator_ Allocator;
private:
typedef Geometry_traits_2 Gt2;
typedef My_visitor<Gt2, Allocator> Self;
typedef CGAL::Surface_sweep_2::Default_visitor
<Self, Gt2, Allocator,
My_event<GeometryTraits_2, Allocator_>,
My_construction_subcurve<GeometryTraits_2,
My_event<GeometryTraits_2, Allocator_>,
Allocator_>> Base;
public:
typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2;
typedef typename Gt2::Point_2 Point_2;
typedef typename Base::Event Event;
typedef typename Base::Subcurve Subcurve;
typedef typename Subcurve::Status_line_iterator Status_line_iterator;
protected:
// Data members:
Partial_hds& m_partial_hds;
bool m_before_strip, m_after_strip;
std::size_t m_nb_intersections;
public:
My_visitor(Partial_hds& a_partial_hds) :
m_partial_hds(a_partial_hds),
m_before_strip(true),
m_after_strip(false),
m_nb_intersections(0)
{}
template<typename Container>
void sweep(const Container& all_segments, bool crop=false, std::size_t id=1)
{
m_partial_hds.m_nb_input_segments=0;
std::vector<X_monotone_curve_2> curves_vec;
if (m_partial_hds.number_of_strips()==1)
{ curves_vec.reserve(all_segments.size()); }
else
{
curves_vec.reserve((2*all_segments.size())/(m_partial_hds.number_of_strips()));
}
bool concerned=false, cropx1, cropx2;
EPECK::Line_2 line;
double val;
ECoord x1, y1;
ECoord x2, y2;
auto it=all_segments.begin();
for (; it!=all_segments.end(); ++id, ++it)
{
if (it->source()!=it->target())
{
concerned=false;
if (it->source().x()<m_partial_hds.m_minx)
{
if (it->target().x()>=m_partial_hds.m_minx)
{ concerned=true; }
}
else
{
if (it->source().x()<m_partial_hds.m_maxx)
{ concerned=true; }
}
if (concerned)
{
if (crop)
{
if (it->source().x()<m_partial_hds.m_minx) { cropx1=true; }
else { cropx1=false; }
if (it->target().x()>m_partial_hds.m_maxx) { cropx2=true; }
else { cropx2=false; }
if (cropx1 || cropx2)
{
line=EPECK::Line_2(EPoint(it->source().x(), it->source().y()),
EPoint(it->target().x(), it->target().y()));
if (cropx1)
{
val=m_partial_hds.m_minx-
((m_partial_hds.m_maxx-m_partial_hds.m_minx)/10000.);
if (val<it->source().x())
{ cropx1=false; }
else
{ x1=val; y1=line.y_at_x(x1); } // Exact coordinates
}
if (cropx2)
{ x2=m_partial_hds.m_maxx; y2=line.y_at_x(x2); }
}
if (!cropx1)
{ x1=it->source().x(); y1=it->source().y(); }
if (!cropx2)
{ x2=it->target().x(); y2=it->target().y(); }
curves_vec.push_back(X_monotone_curve_2(ESegment(EPoint(x1,y1),
EPoint(x2, y2)),
id));
}
else
{
curves_vec.push_back(X_monotone_curve_2
(ESegment(EPoint(it->source().x(), it->source().y()),
EPoint(it->target().x(), it->target().y())),
id));
}
++m_partial_hds.m_nb_input_segments;
}
}
}
// 2) Perform the sweep.
My_surface_sweep_2<Self>* sl = reinterpret_cast<My_surface_sweep_2<Self>*>
(this->surface_sweep());
sl->sweep_until(curves_vec.begin(), curves_vec.end(),
m_partial_hds.m_max);
}
void enter_in_strip()
{ m_before_strip=false; }
void end_of_strip()
{ m_after_strip=true; }
HDS& hds()
{ return m_partial_hds.hds(); }
const EPoint& pmin() const
{ return m_partial_hds.pmin(); }
const EPoint& pmax() const
{ return m_partial_hds.pmax(); }
std::size_t strip_id() const
{ return m_partial_hds.strip_id(); }
std::size_t number_of_strips() const
{ return m_partial_hds.number_of_strips(); }
std::size_t number_of_intersections() const
{ return m_nb_intersections; }
// Before to process the given event in the sweep line
void before_handle_event(Event* event)
{
assert(event->is_closed());
assert(event->vertex_handle()==nullptr);
if (m_before_strip)
{ event->set_before_strip(); return; }
if (m_after_strip) return;
assert(m_partial_hds.point_in_strip(event->point()));
event->set_vertex_handle(hds().create_vertex(event->point()));
/* print_txt_with_endl("[strip", m_partial_hds.strip_id(),
"] Create inner point for [",event->point()); */
}
// After having proceed the given even in the sweep line
bool after_handle_event(Event* event,
Status_line_iterator iter,
bool /*is_event_on_above*/)
{
// print_txt_with_endl("after_handle_event ", event, " ", event->point());
Halfedge_handle prevhh=nullptr;
if (event->vertex_handle()!=nullptr)
{ // Point in strip
typename Event::Subcurve_reverse_iterator subcurve_rit;
for (subcurve_rit=event->left_curves_rbegin();
subcurve_rit!=event->left_curves_rend(); ++subcurve_rit)
{
hds().set_vertex(hds().opposite((*subcurve_rit)->halfedge()),
event->vertex_handle());
prevhh=hds().add_segment_around_vertex
(hds().opposite((*subcurve_rit)->halfedge()),
event->vertex_handle(), prevhh);
if ((*subcurve_rit)->last_event()->vertex_handle()==nullptr)
{ m_partial_hds.add_left_external_halfedge((*subcurve_rit)->halfedge()); }
}
if (event->is_intersection() || event->is_weak_intersection())
{ ++m_nb_intersections; }
}
else if (m_after_strip)
{
typename Event::Subcurve_reverse_iterator subcurve_rit;
for (subcurve_rit=event->left_curves_rbegin();
subcurve_rit!=event->left_curves_rend(); ++subcurve_rit)
{
if ((*subcurve_rit)->last_event()->vertex_handle()!=nullptr ||
(*subcurve_rit)->last_event()->before_strip())
{
/* print_txt_with_endl("right_segment ",
(*subcurve_rit)->last_event()->point(),
" -> ", event->point()); */
m_partial_hds.add_right_external_halfedge
(hds().opposite((*subcurve_rit)->halfedge()));
if ((*subcurve_rit)->last_event()->before_strip())
{ m_partial_hds.add_left_external_halfedge((*subcurve_rit)->halfedge()); }
}
}
typename Event::Subcurve_iterator subcurve_it;
for (subcurve_it=event->right_curves_begin();
subcurve_it!=event->right_curves_end(); ++subcurve_it)
{ (*subcurve_it)->set_last_event(event); }
}
else
{
assert(m_before_strip);
typename Event::Subcurve_reverse_iterator subcurve_rit;
for (subcurve_rit=event->left_curves_rbegin();
subcurve_rit!=event->left_curves_rend(); ++subcurve_rit)
{
// Case of an edge entirely before the strip: ignore
hds().erase_edge((*subcurve_rit)->halfedge());
(*subcurve_rit)->set_halfedge(nullptr);
}
}
if (!m_after_strip)
{
typename Event::Subcurve_iterator subcurve_it;
for (subcurve_it=event->right_curves_begin();
subcurve_it!=event->right_curves_end(); ++subcurve_it)
{
(*subcurve_it)->set_halfedge
(hds().create_edge
(event->vertex_handle(), (*subcurve_it)->original_segment_id()));
if (event->vertex_handle()!=nullptr)
{
prevhh=hds().add_segment_around_vertex
((*subcurve_it)->halfedge(), event->vertex_handle(), prevhh);
}
(*subcurve_it)->set_last_event(event);
}
}
if (event->vertex_handle()!=nullptr)
{
hds().end_of_vertex(event->vertex_handle(), prevhh);
// Iter is on the status line just after event
Halfedge_handle fatherdart=(iter!=this->status_line_end()?
(*iter)->halfedge():nullptr);
m_partial_hds.set_above_halfedge(event->vertex_handle(), fatherdart);
}
return (event->number_of_right_curves() == 0);
}
void found_overlap(Subcurve* sc1,
Subcurve* sc2,
Subcurve* ov_sc)
{
ov_sc->set_original_segment_id(std::min(sc1->original_segment_id(),
sc2->original_segment_id()));
}
};
#endif
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef PARTIAL_HDS_H
#define PARTIAL_HDS_H
#include <iostream>
#include <thread>
#include <vector>
#include <tuple>
#include <stack>
#include <map>
#include "Print_txt.h"
#include "Hds.h"
#include "Export_xfig.hh"
template <typename GeometryTraits_2, typename Allocator_>
class My_visitor;
template <typename Kernel_>
class My_arr_segment_traits_2;
class SHds;
////////////////////////////////////////////////////////////////////////////////
class Partial_hds
{
public:
using Self=Partial_hds;
template <typename GeometryTraits_2, typename Allocator_>
friend class My_visitor;
friend class SHds;
friend class MySimpleSHDSViewerQt;
Partial_hds(double x1=0., double y1=0., double x2=0., double y2=0.,
std::size_t strip_id=0, std::size_t nb_strips=0):
m_minx(x1),
m_maxx(x2),
m_min(x1, y1),
m_max(x2, y2),
m_strip_id(strip_id),
m_nb_strips(nb_strips),
m_nb_input_segments(0)
{
/*print_txt_with_endl("[Strip ", m_strip_id, "]: ", x1, ", ",
y1, ", ", x2, ", ", y2); */
}
std::size_t strip_id() const
{ return m_strip_id; }
std::size_t number_of_strips() const
{ return m_nb_strips; }
ECoord xmin() const
{ return m_min.x(); }
ECoord ymin() const
{ return m_min.y(); }
ECoord xmax() const
{ return m_max.x(); }
ECoord ymax() const
{ return m_max.y(); }
const EPoint& pmin() const
{ return m_min; }
const EPoint& pmax() const
{ return m_max; }
HDS& hds()
{ return m_hds; }
const HDS& hds() const
{ return m_hds; }
std::size_t number_of_left_externals() const
{ return m_left_external_halfedges.size(); }
std::size_t number_of_right_externals() const
{ return m_right_external_halfedges.size(); }
std::size_t number_of_externals() const
{ return number_of_left_externals()+number_of_right_externals(); }
std::size_t number_of_non_externals() const
{ return hds().number_of_halfedges()-number_of_externals(); }
std::size_t number_of_input_segments() const
{ return m_nb_input_segments; }
void clear()
{
m_minx=m_maxx=0;
m_min=m_max=CGAL::ORIGIN;
m_strip_id=m_nb_strips=0;
m_hds.clear();
m_left_external_halfedges.clear();
m_right_external_halfedges.clear();
}
bool point_in_strip(const EPoint& p) const
{
// in strip means p.x >= m_min.x && p.x < m_max.x
return (CGAL::compare_x(p, m_min)!=CGAL::SMALLER &&
CGAL::compare_x(p, m_max)==CGAL::SMALLER);
}
void add_left_external_halfedge(Halfedge_handle hh)
{
/*print_txt_with_endl("[strip ", strip_id(), "] add_left_external_halfedge ",
hds().edge_id(hh), " ptr=", &*hh);*/
assert(is_left_external(hh));
assert(m_left_external_halfedges.count(hds().edge_id(hh))==0);
assert(hds().left_to_right(hh));
m_left_external_halfedges.insert(std::make_pair(hds().edge_id(hh), hh));
}
void add_right_external_halfedge(Halfedge_handle hh)
{
/*print_txt_with_endl("[strip ", strip_id(), "] add_right_external_halfedge ",
-hds().edge_id(hh), " ptr=", &*hh);*/
assert(is_right_external(hh));
assert(m_right_external_halfedges.count(-hds().edge_id(hh))==0);
assert(hds().right_to_left(hh));
m_right_external_halfedges.insert(std::make_pair(-hds().edge_id(hh), hh));
}
void set_above_halfedge(Vertex_handle vh, Halfedge_handle hh)
{ vh->set_above_halfedge(hh); }
// @return true iff hh is external, i.e. not linked with an inner point in
// this strip.
bool is_external(Halfedge_handle hh) const
{ return hds().vertex(hh)==nullptr; }
// @return true iff hh is left external, i.e. external and intersect the
// left side of the strip (and thus from left to right).
bool is_left_external(Halfedge_handle hh) const
{ return is_external(hh) && hds().left_to_right(hh); }
// @return true iff hh is right external, i.e. external and intersect the
// right side of the strip (and thus from right to left).
bool is_right_external(Halfedge_handle hh) const
{ return is_external(hh) && hds().right_to_left(hh); }
bool source_in_strip(Halfedge_handle hh) const
{ return !is_external(hh); }
bool target_in_strip(Halfedge_handle hh) const
{ return !is_external(hds().opposite(hh)); }
bool is_valid_external_halfedges()
{
bool res=true;
if (m_strip_id==0 && !m_left_external_halfedges.empty())
{
print_txt_with_endl("[strip 0] : ERROR m_left_external_halfedges "
"is not empty.");
}
if (m_strip_id==m_nb_strips-1 && !m_right_external_halfedges.empty())
{
print_txt_with_endl("[strip ", strip_id(),
"] (last strip) : ERROR, m_right_external_halfedges "
"is not empty.");
}
for (auto it=hds().halfedges().begin(), itend=hds().halfedges().end();
it!=itend; ++it)
{
if (is_left_external(it))
{
auto resfind=m_left_external_halfedges.find(hds().edge_id(it));
if (resfind==m_left_external_halfedges.end())
{ print_txt_with_endl("[strip ", strip_id(),
"] : ERROR, halfedge ",
hds().edge_id(it), " is left external but ",
"is not in array m_left_external_halfedges.");
res=false;
}
else
{
if (resfind->second!=it)
{ print_txt_with_endl("[strip ", strip_id(),
"] : ERROR, halfedge ",
hds().edge_id(it), " is left external but ",
"its associated halfedge in array ",
"m_left_external_halfedges is different ",
hds().edge_id(resfind->second),
" PTR ", &*(resfind->second), " AND ",
&*(it));
res=false;
}
}
}
if (is_right_external(it))
{
auto resfind=m_right_external_halfedges.find(-hds().edge_id(it));
if (resfind==m_right_external_halfedges.end())
{ print_txt_with_endl("[strip ", strip_id(),
"] : ERROR, halfedge ",
hds().edge_id(it), " is right external but ",
"is not in array m_right_external_halfedges.");
res=false;
}
else
{
if (resfind->second!=it)
{ print_txt_with_endl("[strip ", strip_id(),
"] : ERROR, halfedge ",
hds().edge_id(it), " is right external but ",
"its associated halfedge in array ",
"m_right_external_halfedges is different ",
hds().edge_id(resfind->second));
res=false;
}
}
}
}
return res;
}
friend std::ostream& operator<<(std::ostream& os,
const Partial_hds& la)
{
CGAL::exact(la.m_min); CGAL::exact(la.m_max);
os<<std::setprecision(17)
<<la.m_minx<<" "<<la.m_maxx<<" "<<la.m_min<<" "<<la.m_max<<" "
<<la.m_strip_id<<" "<<la.m_nb_strips<<" "<<la.m_nb_input_segments
<<std::endl<<std::endl;
os<<la.m_hds<<std::endl;
os<<la.m_left_external_halfedges.size()<<" "
<<la.m_right_external_halfedges.size()<<std::endl;
for (auto it=la.m_left_external_halfedges.begin(),
itend=la.m_left_external_halfedges.end(); it!=itend; ++it)
{ os<<it->first<<" "<<la.hds().halfedges().index(it->second)<<std::endl; }
for (auto it=la.m_right_external_halfedges.begin(),
itend=la.m_right_external_halfedges.end(); it!=itend; ++it)
{ os<<it->first<<" "<<la.hds().halfedges().index(it->second)<<std::endl; }
return os;
}
friend std::istream& operator>>(std::istream& is,
Partial_hds& la)
{
la.clear();
is>>la.m_minx>>la.m_maxx>>la.m_min>>la.m_max
>>la.m_strip_id>>la.m_nb_strips>>la.m_nb_input_segments;
std::vector<Halfedge_handle> halfedges;
std::vector<Vertex_handle> vertices;
la.m_hds.load(is, halfedges, vertices);
std::size_t nb_left, nb_right;
std::size_t ind1;
int int1;
is>>nb_left>>nb_right;
for (std::size_t i=0; i<nb_left; ++i)
{
is>>int1>>ind1;
la.m_left_external_halfedges[int1]=halfedges[ind1];
}
for (std::size_t i=0; i<nb_right; ++i)
{
is>>int1>>ind1;
la.m_right_external_halfedges[int1]=halfedges[ind1];
}
return is;
}
void display_info() const
{
print_txt_with_endl("[strip ", m_strip_id, "]: (", m_minx, " -> ", m_maxx,
") #input-segments ", m_nb_input_segments,
" #left-external=", m_left_external_halfedges.size(),
" #right-external=", m_right_external_halfedges.size(),
" #halfedges=", hds().number_of_halfedges(),
" #vertices=", hds().number_of_vertices());
}
void export_to_xfig(Export_xfig& export_xfig,
double dx, double dy,
uint8_t coul_segments,
uint8_t coul_disks,
uint8_t coul_borders,
uint16_t width_segments,
uint16_t radius_disks,
uint16_t width_borders) const
{
// Border of the strip
if (width_borders>0)
{
export_xfig.rectangle(CGAL::to_double(m_min.x())+dx,
CGAL::to_double(m_min.y())+dy,
CGAL::to_double(m_max.x())+dx,
CGAL::to_double(m_max.y())+dy,
coul_borders, width_borders, false, 200);
}
// HDS
hds().export_to_xfig(export_xfig, dx, dy,
coul_segments, coul_disks,
width_segments, radius_disks);
}
protected:
double m_minx, m_maxx;
EPoint m_min, m_max;
std::size_t m_strip_id;
std::size_t m_nb_strips;
std::size_t m_nb_input_segments;
HDS m_hds;
std::unordered_map<int, Halfedge_handle> m_left_external_halfedges;
std::unordered_map<int, Halfedge_handle> m_right_external_halfedges;
};
////////////////////////////////////////////////////////////////////////////////
#endif // PARTIAL_HDS_H
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef PRINT_TXT_H
#define PRINT_TXT_H
#include <sstream>
#include <utility>
#include <chrono>
///////////////////////////////////////////////////////////////////////////////
template<typename T>
void put_one_value(std::ostringstream& txt, const T& v)
{ txt<<v; }
//----------------------------------------------------------------------------
template<>
void put_one_value(std::ostringstream& txt,
const std::chrono::duration<double>& v)
{
std::chrono::seconds s=std::chrono::duration_cast<std::chrono::seconds>(v);
txt<<v.count();
}
///////////////////////////////////////////////////////////////////////////////
template <typename Arg, typename... Args>
void print_txt(Arg&& arg, Args&&... args)
{
std::ostringstream txt;
put_one_value(txt, std::forward<Arg>(arg));
using expander = int[];
(void)expander{0, (void(put_one_value(txt, std::forward<Args>(args))),0)...};
std::cout<<txt.str()<<std::flush;
}
///////////////////////////////////////////////////////////////////////////////
template <typename Arg, typename... Args>
void print_txt_with_endl(Arg&& arg, Args&&... args)
{
std::ostringstream txt;
put_one_value(txt, std::forward<Arg>(arg));
using expander = int[];
(void)expander{0, (void(put_one_value(txt, std::forward<Args>(args))),0)...};
txt<<std::endl;
std::cout<<txt.str()<<std::flush;
}
///////////////////////////////////////////////////////////////////////////////
#endif // PRINT_TXT_H
src/SHds.h 0 → 100644
This diff is collapsed.
// compute_arrangement: a new method to compute arrangement of segments.
// Copyright (C) 2020 CNRS and LIRIS' Establishments (France).
//
// 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 <https://www.gnu.org/licenses/>.
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef SHDS_TO_CGAL_ARRANGEMENT_H
#define SHDS_TO_CGAL_ARRANGEMENT_H
#include "SHds.h"
#include <CGAL/Arrangement_2.h>
// Build a CGAL arrangement from a parallel arrangement.
template<typename Arr>
void shds_to_cgal_arrangement(SHds& shds, Arr& arr)
{
arr.clear();
std::vector<ESegment> all_segments;
all_segments.reserve(shds.number_of_non_external_halfedges()/2);
Global_halfedge hh;
for (std::size_t i=0; i<shds.number_of_strips(); ++i)
{
for (auto it=shds.hds(i).halfedges().begin(),
itend=shds.hds(i).halfedges().end(); it!=itend; ++it)
{
if (!shds.partial_hds(i).is_external(it))
{ // First halfedge is it
hh=shds.opposite(Global_halfedge(i, it)); // Opposite halfedge, a non critical dart
if (it<hh.halfedge()) // To add a segment only once
{ all_segments.push_back(ESegment(shds.hds(i).point(it),
shds.hds(hh).point(hh.halfedge()))); }
}
}
}
CGAL::insert_non_intersecting_curves(arr,
all_segments.begin(), all_segments.end());
}
#endif // SHDS_TO_CGAL_ARRANGEMENT_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Author: David Robert Nadeau
* Site: http://NadeauSoftware.com/
* License: Creative Commons Attribution 3.0 Unported License
* http://creativecommons.org/licenses/by/3.0/deed.en_US
*/
#ifndef MEMORY_H
#define MEMORY_H
#if defined(_WIN32)
#include <windows.h>
#include <psapi.h>
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/resource.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach.h>
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
#include <fcntl.h>
#include <procfs.h>
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include <stdio.h>
#endif
#else
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif
/**
* Returns the peak (maximum so far) resident set size (physical
* memory use) measured in bytes, or zero if the value cannot be
* determined on this OS.
*/
size_t getPeakRSS( )
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.PeakWorkingSetSize;
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
/* AIX and Solaris ------------------------------------------ */
struct psinfo psinfo;
int fd = -1;
if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
return (size_t)0L; /* Can't open? */
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
{
close( fd );
return (size_t)0L; /* Can't read? */
}
close( fd );
return (size_t)(psinfo.pr_rssize * 1024L);
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* BSD, Linux, and OSX -------------------------------------- */
struct rusage rusage;
getrusage( RUSAGE_SELF, &rusage );
#if defined(__APPLE__) && defined(__MACH__)
return (size_t)rusage.ru_maxrss;
#else
return (size_t)(rusage.ru_maxrss * 1024L);
#endif
#else
/* Unknown OS ----------------------------------------------- */
return (size_t)0L; /* Unsupported. */
#endif
}
/**
* Returns the current resident set size (physical memory use) measured
* in bytes, or zero if the value cannot be determined on this OS.
*/
size_t getCurrentRSS( )
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.WorkingSetSize;
#elif defined(__APPLE__) && defined(__MACH__)
/* OSX ------------------------------------------------------ */
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
(task_info_t)&info, &infoCount ) != KERN_SUCCESS )
return (size_t)0L; /* Can't access? */
return (size_t)info.resident_size;
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
/* Linux ---------------------------------------------------- */
long rss = 0L;
FILE* fp = NULL;
if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
return (size_t)0L; /* Can't open? */
if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
{
fclose( fp );
return (size_t)0L; /* Can't read? */
}
fclose( fp );
return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
#else
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
return (size_t)0L; /* Unsupported. */
#endif
}
#endif // MEMORY_H
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment