WIP: operations almost all working in regular cases

This commit is contained in:
Simon Giraudot 2019-06-06 14:56:45 +02:00
parent 683d783cdd
commit aaf05585b5
11 changed files with 1485 additions and 522 deletions

View File

@ -1317,6 +1317,72 @@ flip_edge(typename boost::graph_traits<Graph>::halfedge_descriptor h,
set_halfedge(foh,oh,g);
}
/// \todo document me
template <typename Graph>
void shift_source (typename boost::graph_traits<Graph>::halfedge_descriptor h,
Graph& g)
{
typedef typename boost::graph_traits<Graph> Traits;
typedef typename Traits::halfedge_descriptor halfedge_descriptor;
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef typename Traits::face_descriptor face_descriptor;
halfedge_descriptor hp = prev (h, g);
halfedge_descriptor ho = opposite (h, g);
halfedge_descriptor hon = next (ho, g);
halfedge_descriptor hpp = prev (hp, g);
vertex_descriptor vppt = target (hpp, g);
face_descriptor f = face (h, g);
face_descriptor fo = face (ho, g);
CGAL_assertion (f != Traits::null_face());
CGAL_assertion (fo != Traits::null_face());
if (halfedge (f, g) == hp)
set_halfedge (f, h, g);
set_next (ho, hp, g);
set_next (hp, hon, g);
set_next (hpp, h, g);
set_target (ho, vppt, g);
set_face (hp, fo, g);
}
/// \todo document me
template <typename Graph>
void shift_target (typename boost::graph_traits<Graph>::halfedge_descriptor h,
Graph& g)
{
typedef typename boost::graph_traits<Graph> Traits;
typedef typename Traits::halfedge_descriptor halfedge_descriptor;
typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef typename Traits::face_descriptor face_descriptor;
halfedge_descriptor hn = next (h, g);
halfedge_descriptor ho = opposite (h, g);
halfedge_descriptor hop = prev (ho, g);
halfedge_descriptor hnn = next (hn, g);
vertex_descriptor vnt = target (hn, g);
face_descriptor f = face (h, g);
face_descriptor fo = face (ho, g);
CGAL_assertion (f != Traits::null_face());
CGAL_assertion (fo != Traits::null_face());
if (halfedge (f, g) == hn)
set_halfedge (f, h, g);
set_next (hop, hn, g);
set_next (hn, ho, g);
set_next (h, hnn, g);
set_target (h, vnt, g);
set_face (hn, fo, g);
}
/**
* \returns `true` if `e` satisfies the *link condition* \cgalCite{degn-tpec-98}, which guarantees that the surface is also 2-manifold after the edge collapse.
*/

View File

@ -2,7 +2,7 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#define CGAL_KSR_VERBOSE_LEVEL 3
#define CGAL_KSR_VERBOSE_LEVEL 4
#include <CGAL/Kinetic_shape_reconstruction_3.h>
#include <CGAL/IO/PLY_reader.h>

View File

@ -53,6 +53,26 @@ void dump_intersection_edges (const DS& data, const std::string& tag = std::stri
out << "2 " << data.segment_3 (iedge) << std::endl;
}
template <typename DS>
void dump_segmented_edges (const DS& data, const std::string& tag = std::string())
{
std::vector<std::ofstream*> out;
for (KSR::size_t i = 0; i < data.nb_intersection_lines(); ++ i)
{
std::string filename = (tag != std::string() ? tag + "_" : "") + "intersection_line_" + std::to_string(i) + ".polylines.txt";
out.push_back (new std::ofstream (filename));
out.back()->precision(18);
}
for (const typename DS::IEdge& iedge : data.iedges())
{
CGAL_assertion (data.line_idx(iedge) != KSR::no_element());
*(out[data.line_idx(iedge)]) << "2 " << data.segment_3 (iedge) << std::endl;
}
for (std::ofstream* o : out)
delete o;
}
template <typename DS>
void dump_constrained_edges (const DS& data, const std::string& tag = std::string())
{
@ -84,53 +104,53 @@ void dump_polygons (const DS& data, const std::string& tag = std::string())
Uchar_map bbox_green = bbox_mesh.template add_property_map<typename Mesh::Face_index, unsigned char>("green", 0).first;
Uchar_map bbox_blue = bbox_mesh.template add_property_map<typename Mesh::Face_index, unsigned char>("blue", 0).first;
KSR::size_t bbox_nb_vertices = 0;
KSR::size_t nb_vertices = 0;
KSR::vector<typename Mesh::Vertex_index> vertices;
KSR::vector<typename Mesh::Vertex_index> map_vertices;
for (KSR::size_t i = 0; i < data.number_of_support_planes(); ++ i)
{
if (data.is_bbox_support_plane(i))
{
KSR::size_t new_vertices = 0;
map_vertices.clear();
for (typename DS::PVertex pvertex : data.pvertices(i))
{
bbox_mesh.add_vertex (data.point_3(pvertex));
++ new_vertices;
if (map_vertices.size() <= pvertex.second)
map_vertices.resize (pvertex.second + 1);
map_vertices[pvertex.second] = bbox_mesh.add_vertex (data.point_3(pvertex));
}
for (typename DS::PFace pface : data.pfaces(i))
{
vertices.clear();
for(typename DS::PVertex pvertex : data.pvertices_of_pface(pface))
vertices.push_back (typename Mesh::Vertex_index(KSR::size_t(pvertex.second) + bbox_nb_vertices));
vertices.push_back (map_vertices[pvertex.second]);
typename Mesh::Face_index face = bbox_mesh.add_face (vertices);
std::tie (bbox_red[face], bbox_green[face], bbox_blue[face])
= get_idx_color ((i+1) * (pface.second+1));
}
bbox_nb_vertices += new_vertices;
}
else
{
KSR::size_t new_vertices = 0;
map_vertices.clear();
for (typename DS::PVertex pvertex : data.pvertices(i))
{
mesh.add_vertex (data.point_3 (pvertex));
++ new_vertices;
if (map_vertices.size() <= pvertex.second)
map_vertices.resize (pvertex.second + 1);
map_vertices[pvertex.second] = mesh.add_vertex (data.point_3 (pvertex));
}
for (typename DS::PFace pface : data.pfaces(i))
{
vertices.clear();
for(typename DS::PVertex pvertex : data.pvertices_of_pface(pface))
vertices.push_back (typename Mesh::Vertex_index(KSR::size_t(pvertex.second) + nb_vertices));
vertices.push_back (map_vertices[pvertex.second]);
typename Mesh::Face_index face = mesh.add_face (vertices);
std::tie (red[face], green[face], blue[face])
= get_idx_color (i * (pface.second+1));
}
nb_vertices += new_vertices;
}
}
@ -139,7 +159,7 @@ void dump_polygons (const DS& data, const std::string& tag = std::string())
CGAL::set_binary_mode (out);
CGAL::write_ply(out, mesh);
#if 1
#if 0
std::string bbox_filename = (tag != std::string() ? tag + "_" : "") + "bbox_polygons.ply";
std::ofstream bbox_out (bbox_filename);
CGAL::set_binary_mode (bbox_out);
@ -148,19 +168,57 @@ void dump_polygons (const DS& data, const std::string& tag = std::string())
}
template <typename DS>
void dump_polygon_borders (const DS& data, const std::string& tag = std::string())
{
std::string filename = (tag != std::string() ? tag + "_" : "") + "polygon_borders.polylines.txt";
std::ofstream out (filename);
for (KSR::size_t i = 6; i < data.number_of_support_planes(); ++ i)
for (const typename DS::PEdge pedge : data.pedges(i))
out << "2 " << data.segment_3 (pedge) << std::endl;
}
template <typename DS, typename Event>
void dump_event (const DS& data, const Event& ev, const std::string& tag = std::string())
{
std::string lfilename = (tag != std::string() ? tag + "_" : "") + "event_line.polylines.txt";
std::ofstream lout (lfilename);
lout.precision(18);
if (ev.is_pvertex_to_pvertex())
{
std::string vfilename = (tag != std::string() ? tag + "_" : "") + "event_pvertex.xyz";
std::ofstream vout (vfilename);
vout.precision(18);
vout << data.point_3 (ev.pvertex()) << std::endl;
// TODO
std::string ofilename = (tag != std::string() ? tag + "_" : "") + "event_pother.xyz";
std::ofstream oout (ofilename);
oout.precision(18);
oout << data.point_3 (ev.pother()) << std::endl;
}
else if (ev.is_pvertex_to_iedge())
{
std::string lfilename = (tag != std::string() ? tag + "_" : "") + "event_iedge.polylines.txt";
std::ofstream lout (lfilename);
lout.precision(18);
lout << "2 " << data.segment_3 (ev.iedge()) << std::endl;
std::string vfilename = (tag != std::string() ? tag + "_" : "") + "event_pvertex.xyz";
std::ofstream vout (vfilename);
vout.precision(18);
vout << data.point_3 (ev.pvertex());
}
else if (ev.is_pvertex_to_ivertex())
{
std::string vfilename = (tag != std::string() ? tag + "_" : "") + "event_pvertex.xyz";
std::ofstream vout (vfilename);
vout.precision(18);
vout << data.point_3 (ev.pvertex()) << std::endl;
std::string ofilename = (tag != std::string() ? tag + "_" : "") + "event_ivertex.xyz";
std::ofstream oout (ofilename);
oout.precision(18);
oout << data.point_3 (ev.ivertex()) << std::endl;
}
std::string vfilename = (tag != std::string() ? tag + "_" : "") + "event_vertex.xyz";
std::ofstream vout (vfilename);
vout.precision(18);
// vout << data.point_of_vertex(ev.vertex_idx()) << std::endl;
}
template <typename DS>
@ -168,10 +226,12 @@ void dump (const DS& data, const std::string& tag = std::string())
{
dump_intersection_edges (data, tag);
dump_constrained_edges (data, tag);
dump_polygon_borders (data, tag);
dump_polygons (data, tag);
}
} // namespace KSR_3
} // namespace CGAL

View File

@ -48,40 +48,94 @@ public:
typedef Event_queue<Data> Queue;
friend Queue;
enum Type
{
FREE_VERTEX_TO_INTERSECTION_EDGE,
CONSTRAINED_VERTEX_TO_FREE_VERTEX,
CONSTRAINED_VERTEX_TO_INTERSECTION_VERTEX,
CONSTRAINED_VERTEX_TO_CONSTRAINED_VERTEX,
EDGE_TO_INTERSECTION_EDGE
};
private:
PVertex m_pvertex;
PVertex m_pother;
IEdge m_iedge;
IVertex m_ivertex;
FT m_time;
public:
Event () { }
Event ()
: m_pvertex (Data::null_pvertex())
, m_pother (Data::null_pvertex())
, m_iedge (Data::null_iedge())
, m_ivertex (Data::null_ivertex())
, m_time (0)
{ }
Event (PVertex pvertex, PVertex pother, FT time)
: m_pvertex (pvertex)
, m_pother (pother)
, m_iedge (Data::null_iedge())
, m_ivertex (Data::null_ivertex())
, m_time (time)
{ }
Event (PVertex pvertex, IEdge iedge, FT time)
: m_pvertex (pvertex)
, m_iedge (iedge), m_time (time)
, m_pother (Data::null_pvertex())
, m_iedge (iedge)
, m_ivertex (Data::null_ivertex())
, m_time (time)
{ }
Event (PVertex pvertex, IVertex ivertex, FT time)
: m_pvertex (pvertex)
, m_pother (Data::null_pvertex())
, m_iedge (Data::null_iedge())
, m_ivertex (ivertex)
, m_time (time)
{ }
Event (PVertex pvertex, PVertex pother, IVertex ivertex, FT time)
: m_pvertex (pvertex)
, m_pother (pother)
, m_iedge (Data::null_iedge())
, m_ivertex (ivertex)
, m_time (time)
{ }
PVertex pvertex() const { return m_pvertex; }
PVertex pother() const { return m_pother; }
IEdge iedge() const { return m_iedge; }
IVertex ivertex() const { return m_ivertex; }
FT time() const { return m_time; }
bool is_pvertex_to_pvertex() const { return (m_pother != Data::null_pvertex()); }
bool is_pvertex_to_iedge() const { return (m_iedge != Data::null_iedge()); }
bool is_pvertex_to_ivertex() const { return (m_pother == Data::null_pvertex()
&& m_ivertex != Data::null_ivertex()); }
bool is_pvertices_to_ivertex() const { return (m_pother != Data::null_pvertex()
&& m_ivertex != Data::null_ivertex()); }
friend std::ostream& operator<< (std::ostream& os, const Event& ev)
{
os << "Event at t=" << ev.m_time << " between vertex ("
<< ev.m_pvertex.first << ":" << ev.m_pvertex.second
<< ") and intersection edge " << ev.m_iedge;
if (ev.is_pvertex_to_pvertex())
os << "Event at t=" << ev.m_time << " between PVertex("
<< ev.m_pvertex.first << ":" << ev.m_pvertex.second
<< ") and PVertex(" << ev.m_pother.first << ":" << ev.m_pother.second << ")";
else if (ev.is_pvertex_to_iedge())
os << "Event at t=" << ev.m_time << " between PVertex("
<< ev.m_pvertex.first << ":" << ev.m_pvertex.second
<< ") and IEdge" << ev.m_iedge;
else if (ev.is_pvertex_to_ivertex())
os << "Event at t=" << ev.m_time << " between PVertex("
<< ev.m_pvertex.first << ":" << ev.m_pvertex.second
<< ") and IVertex(" << ev.m_ivertex << ")";
else if (ev.is_pvertices_to_ivertex())
os << "Event at t=" << ev.m_time << " between PVertex("
<< ev.m_pvertex.first << ":" << ev.m_pvertex.second
<< "), PVertex(" << ev.m_pother.first << ":" << ev.m_pother.second
<< " and IVertex(" << ev.m_ivertex << ")";
else
os << "Invalid event at t=" << ev.m_time;
return os;
}

View File

@ -59,15 +59,19 @@ private:
boost::multi_index::ordered_non_unique
<boost::multi_index::member<Event, FT, &Event::m_time> >,
boost::multi_index::ordered_non_unique
<boost::multi_index::member<Event, PVertex, &Event::m_pvertex> >
<boost::multi_index::member<Event, PVertex, &Event::m_pvertex> >,
boost::multi_index::ordered_non_unique
<boost::multi_index::member<Event, PVertex, &Event::m_pother> >
>
> Queue;
typedef typename Queue::iterator Queue_iterator;
typedef typename Queue::template nth_index<0>::type Queue_by_time;
typedef typename Queue_by_time::iterator Queue_by_time_iterator;
typedef typename Queue::template nth_index<1>::type Queue_by_event_idx;
typedef typename Queue_by_event_idx::iterator Queue_by_event_idx_iterator;
typedef typename Queue::template nth_index<1>::type Queue_by_pvertex_idx;
typedef typename Queue_by_pvertex_idx::iterator Queue_by_pvertex_idx_iterator;
typedef typename Queue::template nth_index<2>::type Queue_by_pother_idx;
typedef typename Queue_by_pother_idx::iterator Queue_by_pother_idx_iterator;
Queue m_queue;
@ -80,13 +84,16 @@ public:
void push (const Event& ev)
{
CGAL_KSR_CERR(4) << "**** Pushing " << ev << std::endl;
m_queue.insert (ev);
}
const Queue_by_time& queue_by_time() const { return m_queue.template get<0>(); }
const Queue_by_event_idx& queue_by_event_idx() const { return m_queue.template get<1>(); }
const Queue_by_pvertex_idx& queue_by_pvertex_idx() const { return m_queue.template get<1>(); }
const Queue_by_pother_idx& queue_by_pother_idx() const { return m_queue.template get<2>(); }
Queue_by_time& queue_by_time() { return m_queue.template get<0>(); }
Queue_by_event_idx& queue_by_event_idx() { return m_queue.template get<1>(); }
Queue_by_pvertex_idx& queue_by_pvertex_idx() { return m_queue.template get<1>(); }
Queue_by_pother_idx& queue_by_pother_idx() { return m_queue.template get<2>(); }
Event pop ()
{
@ -102,23 +109,28 @@ public:
std::cerr << e << std::endl;
}
void erase_vertex_events (KSR::size_t support_plane_idx, PVertex pvertex)
void erase_vertex_events (PVertex pvertex)
{
std::pair<Queue_by_event_idx_iterator, Queue_by_event_idx_iterator>
range = queue_by_event_idx().equal_range(pvertex);
queue_by_event_idx().erase (range.first, range.second);
{
std::pair<Queue_by_pvertex_idx_iterator, Queue_by_pvertex_idx_iterator>
range = queue_by_pvertex_idx().equal_range(pvertex);
for (const auto& ev : CGAL::make_range(range))
CGAL_KSR_CERR(4) << "**** Erasing " << ev << std::endl;
queue_by_pvertex_idx().erase (range.first, range.second);
}
{
std::pair<Queue_by_pother_idx_iterator, Queue_by_pother_idx_iterator>
range = queue_by_pother_idx().equal_range(pvertex);
for (const auto& ev : CGAL::make_range(range))
CGAL_KSR_CERR(4) << "**** Erasing " << ev << std::endl;
queue_by_pother_idx().erase (range.first, range.second);
}
}
void erase_vertex_events (KSR::size_t support_plane_idx, PVertex pvertex,
KSR::vector<Event>& events)
{
std::pair<Queue_by_event_idx_iterator, Queue_by_event_idx_iterator>
range = queue_by_event_idx().equal_range(pvertex);
std::copy (range.first, range.second, std::back_inserter (events));
queue_by_event_idx().erase (range.first, range.second);
}
};

View File

@ -51,14 +51,19 @@ public:
struct Vertex_property
{
Point_3 point;
bool active;
Vertex_property () { }
Vertex_property (const Point_3& point) : point (point) { }
Vertex_property () : active(true) { }
Vertex_property (const Point_3& point) : point (point), active(true) { }
};
struct Edge_property
{
KSR::size_t line;
KSR::Idx_set planes;
bool active;
Edge_property() : line (KSR::no_element()), active(true) { }
};
typedef boost::adjacency_list <boost::setS,
@ -79,12 +84,13 @@ public:
private:
Graph m_graph;
KSR::size_t m_nb_lines;
std::map<Point_3, Vertex_descriptor> m_map_points;
std::map<KSR::Idx_vector, Vertex_descriptor> m_map_vertices;
public:
Intersection_graph() { }
Intersection_graph() : m_nb_lines(0) { }
static Vertex_descriptor null_ivertex()
{ return boost::graph_traits<Graph>::null_vertex(); }
@ -121,6 +127,9 @@ public:
return std::make_pair (iter->second, inserted);
}
KSR::size_t add_line() { return (m_nb_lines ++); }
KSR::size_t nb_lines() const { return m_nb_lines; }
std::pair<Edge_descriptor, bool> add_edge (const Vertex_descriptor& source, const Vertex_descriptor& target,
KSR::size_t support_plane_idx)
{
@ -144,6 +153,13 @@ public:
return add_edge (add_vertex (source).first, add_vertex (target).first);
}
void set_line (const Edge_descriptor& edge, KSR::size_t line_idx)
{
m_graph[edge].line = line_idx;
}
KSR::size_t line (const Edge_descriptor& edge) const { return m_graph[edge].line; }
std::pair<Edge_descriptor, Edge_descriptor>
split_edge (const Edge_descriptor& edge, const Vertex_descriptor& vertex)
{
@ -210,6 +226,11 @@ public:
return Line_3 (m_graph[source (edge, m_graph)].point,
m_graph[target (edge, m_graph)].point);
}
bool is_active (const Vertex_descriptor& vertex) const { return m_graph[vertex].active; }
bool& is_active (const Vertex_descriptor& vertex) { return m_graph[vertex].active; }
bool is_active (const Edge_descriptor& edge) const { return m_graph[edge].active; }
bool& is_active (const Edge_descriptor& edge) { return m_graph[edge].active; }
};

View File

@ -101,7 +101,7 @@ public:
Polygon_splitter (Data& data) : m_data (data) { }
void split_support_plane (KSR::size_t support_plane_idx)
void split_support_plane (KSR::size_t support_plane_idx, unsigned int k)
{
// First, insert polygons
for (PVertex pvertex : m_data.pvertices(support_plane_idx))
@ -254,9 +254,11 @@ public:
}
while (current != edge);
PFace pface = m_data.add_pface (support_plane_idx, new_vertices);
PFace pface = m_data.add_pface (new_vertices);
CGAL_assertion (pface != PFace());
m_data.k(pface) = k;
std::size_t original_idx = 0;
if (original_faces.size() != 1)
{

View File

@ -65,8 +65,10 @@ public:
typedef typename Mesh::template Property_map<Vertex_index, Vector_2> V_vector_map;
typedef typename Mesh::template Property_map<Vertex_index, IVertex> V_ivertex_map;
typedef typename Mesh::template Property_map<Vertex_index, IEdge> V_iedge_map;
typedef typename Mesh::template Property_map<Vertex_index, bool> V_bool_map;
typedef typename Mesh::template Property_map<Edge_index, IEdge> E_iedge_map;
typedef typename Mesh::template Property_map<Face_index, KSR::size_t> F_index_map;
typedef typename Mesh::template Property_map<Face_index, unsigned int> F_uint_map;
private:
@ -78,8 +80,10 @@ private:
V_vector_map direction;
V_ivertex_map v_ivertex_map;
V_iedge_map v_iedge_map;
V_bool_map v_active_map;
E_iedge_map e_iedge_map;
F_index_map input;
F_index_map input_map;
F_uint_map k_map;
std::set<IEdge> iedges;
};
@ -114,12 +118,14 @@ public:
("v:ivertex", Intersection_graph::null_ivertex()).first;
m_data->v_iedge_map = m_data->mesh.template add_property_map<Vertex_index, IEdge>
("v:iedge", Intersection_graph::null_iedge()).first;
m_data->v_active_map = m_data->mesh.template add_property_map<Vertex_index, bool>
("v:active", true).first;
m_data->e_iedge_map = m_data->mesh.template add_property_map<Edge_index, IEdge>
("e:iedge", Intersection_graph::null_iedge()).first;
bool okay;
std::tie (m_data->input, okay) = m_data->mesh.template add_property_map<Face_index, KSR::size_t>("f:input", KSR::no_element());
CGAL_assertion(okay);
m_data->input_map = m_data->mesh.template add_property_map<Face_index, KSR::size_t>
("f:input", KSR::no_element()).first;
m_data->k_map = m_data->mesh.template add_property_map<Face_index, unsigned int>
("f:k", 0).first;
}
const Plane_3& plane() const { return m_data->plane; }
@ -127,6 +133,39 @@ public:
const Mesh& mesh() const { return m_data->mesh; }
Mesh& mesh() { return m_data->mesh; }
void set_point (const Vertex_index& vertex_index, const Point_2& point)
{
m_data->mesh.point(vertex_index) = point;
}
Vertex_index prev (const Vertex_index& vertex_index) const
{
return m_data->mesh.source(m_data->mesh.halfedge(vertex_index));
}
Vertex_index next (const Vertex_index& vertex_index) const
{
return m_data->mesh.target(m_data->mesh.next(m_data->mesh.halfedge(vertex_index)));
}
Face_index face (const Vertex_index& vertex_index) const
{
Face_index out = m_data->mesh.face (m_data->mesh.halfedge(vertex_index));
if (out == Face_index())
out = m_data->mesh.face (m_data->mesh.opposite(m_data->mesh.halfedge(vertex_index)));
CGAL_assertion (out != Face_index());
return out;
}
std::pair<Face_index, Face_index> faces (const Vertex_index& vertex_index) const
{
for (Halfedge_index hi : halfedges_around_target (halfedge(vertex_index, m_data->mesh), m_data->mesh))
if (has_iedge (m_data->mesh.edge(hi)))
return std::make_pair (m_data->mesh.face (hi),
m_data->mesh.face (m_data->mesh.opposite(hi)));
CGAL_assertion_msg (false, "No constrained edge found");
return std::make_pair (Face_index(), Face_index());
}
Point_2 point_2 (const Vertex_index& vertex_index, FT time) const
{ return m_data->mesh.point(vertex_index) + time * m_data->direction[vertex_index]; }
@ -146,7 +185,7 @@ public:
}
void set_iedge (const Vertex_index& a, const Vertex_index& b,
const IEdge& iedge) const
const IEdge& iedge) const
{
Halfedge_index hi = m_data->mesh.halfedge (a, b);
CGAL_assertion (hi != Halfedge_index());
@ -161,11 +200,17 @@ public:
}
void set_iedge (const Vertex_index& vertex,
const IEdge& iedge) const
const IEdge& iedge) const
{
m_data->v_iedge_map[vertex] = iedge;
}
void set_iedge (const Edge_index& edge,
const IEdge& iedge) const
{
m_data->e_iedge_map[edge] = iedge;
}
const IEdge& iedge (const Edge_index& edge_index) const
{
return m_data->e_iedge_map[edge_index];
@ -176,6 +221,11 @@ public:
return m_data->v_iedge_map[vertex_index];
}
const IVertex& ivertex (const Vertex_index& vertex_index) const
{
return m_data->v_ivertex_map[vertex_index];
}
bool has_iedge (const Edge_index& edge_index) const
{
return (m_data->e_iedge_map[edge_index] != Intersection_graph::null_iedge());
@ -184,15 +234,25 @@ public:
{
return (m_data->v_iedge_map[vertex_index] != Intersection_graph::null_iedge());
}
bool has_ivertex (const Vertex_index& vertex_index) const
{
return (m_data->v_ivertex_map[vertex_index] != Intersection_graph::null_ivertex());
}
const Vector_2& direction (const Vertex_index& vertex_index) const { return m_data->direction[vertex_index]; }
Vector_2& direction (const Vertex_index& vertex_index) { return m_data->direction[vertex_index]; }
FT speed (const Vertex_index& vertex_index) const
{ return CGAL::approximate_sqrt (m_data->direction[vertex_index].squared_length()); }
const KSR::size_t& input (const Face_index& face_index) const { return m_data->input[face_index]; }
KSR::size_t& input (const Face_index& face_index) { return m_data->input[face_index]; }
const KSR::size_t& input (const Face_index& face_index) const { return m_data->input_map[face_index]; }
KSR::size_t& input (const Face_index& face_index) { return m_data->input_map[face_index]; }
const unsigned int& k (const Face_index& face_index) const { return m_data->k_map[face_index]; }
unsigned int& k (const Face_index& face_index) { return m_data->k_map[face_index]; }
bool is_active (const Vertex_index& vertex_index) const { return m_data->v_active_map[vertex_index]; }
void set_active (const Vertex_index& vertex_index, bool value) { m_data->v_active_map[vertex_index] = value; }
bool is_frozen (const Vertex_index& vertex_index) const
{
return (m_data->direction[vertex_index] == CGAL::NULL_VECTOR);
@ -239,7 +299,7 @@ public:
}
Face_index fi = m_data->mesh.add_face (vertices);
m_data->input[fi] = KSR::no_element();
m_data->input_map[fi] = KSR::no_element();
return vertices;
}
@ -257,17 +317,14 @@ public:
}
Face_index fi = m_data->mesh.add_face (vertices);
m_data->input[fi] = input_idx;
m_data->input_map[fi] = input_idx;
return KSR::size_t(fi);
}
Edge_index edge (const Vertex_index& v0, const Vertex_index& v1)
{
for (Halfedge_index hi : halfedges_around_target (halfedge(v0, m_data->mesh), m_data->mesh))
if (target(hi, m_data->mesh) == v1)
return m_data->mesh.edge(hi);
return Edge_index();
return m_data->mesh.edge (m_data->mesh.halfedge (v0, v1));
}
Edge_index add_edge (const Vertex_index& v0, const Vertex_index& v1,
@ -283,9 +340,32 @@ public:
return m_data->mesh.add_vertex(point);
}
Vertex_index split_edge (const Edge_index& ei)
Vertex_index duplicate_vertex (const Vertex_index& v)
{
return m_data->mesh.target (CGAL::Euler::split_edge (m_data->mesh.halfedge (ei), m_data->mesh));
Vertex_index vi = m_data->mesh.add_vertex (m_data->mesh.point(v));
m_data->direction[vi] = m_data->direction[v];
m_data->v_ivertex_map[vi] = m_data->v_ivertex_map[v];
m_data->v_iedge_map[vi] = m_data->v_iedge_map[v];
return vi;
}
void remove_vertex (const Vertex_index& v)
{
m_data->mesh.remove_vertex(v);
}
Edge_index split_vertex (const Vertex_index& ei)
{
return m_data->mesh.edge
(CGAL::Euler::split_vertex (m_data->mesh.halfedge (ei),
m_data->mesh.opposite(m_data->mesh.next(m_data->mesh.halfedge (ei))),
m_data->mesh));
}
Vertex_index split_edge (const Vertex_index& v0, const Vertex_index& v1)
{
return m_data->mesh.target
(CGAL::Euler::split_edge (m_data->mesh.halfedge (v0, v1), m_data->mesh));
}

View File

@ -115,8 +115,10 @@ public:
KSR_3::dump (m_data, "init");
CGAL_assertion(check_integrity(true));
make_polygons_intersection_free();
make_polygons_intersection_free(k);
CGAL_assertion(check_integrity(true));
KSR_3::dump_segmented_edges (m_data, "init");
KSR_3::dump (m_data, "intersected");
@ -129,7 +131,7 @@ public:
m_min_time = m_max_time;
m_max_time += time_step;
CGAL_assertion(check_integrity(true));
// CGAL_assertion(check_integrity(true));
++ iter;
}
exit(0);
@ -151,7 +153,7 @@ public:
if (!m_data.mesh_is_valid(i))
{
if (verbose)
std::cerr << "ERROR: Mesh " << i << "is invalid" << std::endl;
std::cerr << "ERROR: Mesh " << i << " is invalid" << std::endl;
return false;
}
@ -161,8 +163,8 @@ public:
{
if (verbose)
std::cerr << "ERROR: Support_plane[" << i
<< "] is intersected by IEdge[" << iedge
<< "] which claims it does not intersect it" << std::endl;
<< "] is intersected by " << m_data.str(iedge)
<< " which claims it does not intersect it" << std::endl;
return false;
}
}
@ -175,8 +177,8 @@ public:
== m_data.iedges(support_plane_idx).end())
{
if (verbose)
std::cerr << "ERROR: IEdge[" << iedge
<< "] intersects Support_plane[" << support_plane_idx
std::cerr << "ERROR: " << m_data.str(iedge)
<< " intersects Support_plane[" << support_plane_idx
<< "] which claims it's not intersected by it" << std::endl;
return false;
}
@ -250,7 +252,7 @@ private:
CGAL_assertion (m_data.iedges().size() == 12);
}
void make_polygons_intersection_free()
void make_polygons_intersection_free (unsigned int k)
{
// First, generate all transverse intersection lines
typedef std::map<KSR::Idx_set, std::pair<IVertex, IVertex> > Map;
@ -324,7 +326,7 @@ private:
for (KSR::size_t i = 0; i < m_data.number_of_support_planes(); ++ i)
{
KSR_3::Polygon_splitter<GeomTraits> splitter (m_data);
splitter.split_support_plane (i);
splitter.split_support_plane (i, k);
}
}
@ -338,68 +340,14 @@ private:
for (KSR::size_t i = 0; i < m_data.number_of_support_planes(); ++ i)
{
// To get random access, copy in vector (suboptimal to do this
// all the time, maybe this should be done once and for all and
// replace the set)
KSR::vector<IEdge> iedges;
iedges.reserve (m_data.iedges(i).size());
std::copy (m_data.iedges(i).begin(),
m_data.iedges(i).end(),
std::back_inserter(iedges));
// Precompute segments and bboxes
KSR::vector<Segment_2> segments_2;
segments_2.reserve (iedges.size());
KSR::vector<CGAL::Bbox_2> segment_bboxes;
segment_bboxes.reserve (iedges.size());
for (const IEdge& iedge : iedges)
{
segments_2.push_back (m_data.segment_2 (i, iedge));
segment_bboxes.push_back (segments_2.back().bbox());
}
init_search_structures (i, iedges, segments_2, segment_bboxes);
for (const PVertex& pvertex : m_data.pvertices(i))
{
if (m_data.is_frozen(pvertex))
continue;
still_running = true;
if (m_data.has_iedge(pvertex)) // Constrained vertex
{
// Test left and right vertices on mesh face
// Test end-vertices of intersection edge
}
else // Unconstrained vertex
{
// Test all intersection edges
Segment_2 si (m_data.point_2 (pvertex, m_min_time),
m_data.point_2 (pvertex, m_max_time));
CGAL::Bbox_2 si_bbox = si.bbox();
for (std::size_t j = 0; j < iedges.size(); ++ j)
{
const IEdge& iedge = iedges[j];
if (m_data.iedge(pvertex) == iedge)
continue;
if (!CGAL::do_overlap (si_bbox, segment_bboxes[j]))
continue;
Point_2 point;
if (!KSR::intersection_2 (si, segments_2[j], point))
continue;
FT dist = CGAL::approximate_sqrt (CGAL::squared_distance (m_data.point_2 (pvertex, m_min_time), point));
FT time = dist / m_data.speed(pvertex);
m_queue.push (Event (pvertex, iedge, m_min_time + time));
}
}
}
if (compute_events_of_vertex (pvertex, iedges, segments_2, segment_bboxes))
still_running = true;
}
m_data.update_positions(m_min_time);
@ -407,6 +355,118 @@ private:
return still_running;
}
void init_search_structures (KSR::size_t i,
KSR::vector<IEdge>& iedges,
KSR::vector<Segment_2>& segments_2,
KSR::vector<CGAL::Bbox_2>& segment_bboxes)
{
// To get random access, copy in vector (suboptimal to do this
// all the time, maybe this should be done once and for all and
// replace the set)
iedges.reserve (m_data.iedges(i).size());
std::copy (m_data.iedges(i).begin(),
m_data.iedges(i).end(),
std::back_inserter(iedges));
// Precompute segments and bboxes
segments_2.reserve (iedges.size());
segment_bboxes.reserve (iedges.size());
for (const IEdge& iedge : iedges)
{
segments_2.push_back (m_data.segment_2 (i, iedge));
segment_bboxes.push_back (segments_2.back().bbox());
}
}
bool compute_events_of_vertex (const PVertex& pvertex,
const KSR::vector<IEdge>& iedges,
const KSR::vector<Segment_2>& segments_2,
const KSR::vector<CGAL::Bbox_2>& segment_bboxes)
{
if (m_data.is_frozen(pvertex))
return false;
Segment_2 sv (m_data.point_2 (pvertex, m_min_time),
m_data.point_2 (pvertex, m_max_time));
CGAL::Bbox_2 sv_bbox = sv.bbox();
if (m_data.has_iedge(pvertex)) // Constrained vertex
{
// Test left and right vertices on mesh face
PVertex prev;
PVertex next;
std::tie (prev, next) = m_data.prev_and_next (pvertex);
for (const PVertex& pother : { prev, next })
{
if (pother == Data::null_pvertex()
|| !m_data.is_active(pother)
|| m_data.has_iedge (pother))
continue;
Segment_2 so (m_data.point_2 (pother, m_min_time),
m_data.point_2 (pother, m_max_time));
CGAL::Bbox_2 so_bbox = so.bbox();
if (!do_overlap (sv_bbox, so_bbox))
continue;
Point_2 point;
if (!KSR::intersection_2 (sv, so, point))
continue;
FT dist = CGAL::approximate_sqrt (CGAL::squared_distance (sv.source(), point));
FT time = dist / m_data.speed(pvertex);
m_queue.push (Event (pvertex, pother, m_min_time + time));
}
// Test end-vertices of intersection edge
IEdge iedge = m_data.iedge(pvertex);
for (const IVertex& ivertex : { m_data.source(iedge), m_data.target(iedge) })
{
if (!m_data.is_active(ivertex))
continue;
Point_2 pi = m_data.to_2d (pvertex.first, ivertex);
if (sv.to_vector() * Vector_2 (sv.source(), pi) < 0)
continue;
FT dist = CGAL::approximate_sqrt(CGAL::squared_distance (sv.source(), pi));
FT time = dist / m_data.speed(pvertex);
if (time < m_max_time - m_min_time)
m_queue.push (Event (pvertex, ivertex, m_min_time + time));
}
}
else // Unconstrained vertex
{
// Test all intersection edges
for (std::size_t j = 0; j < iedges.size(); ++ j)
{
const IEdge& iedge = iedges[j];
if (m_data.iedge(pvertex) == iedge)
continue;
if (!m_data.is_active(iedge))
continue;
if (!CGAL::do_overlap (sv_bbox, segment_bboxes[j]))
continue;
Point_2 point;
if (!KSR::intersection_2 (sv, segments_2[j], point))
continue;
FT dist = CGAL::approximate_sqrt (CGAL::squared_distance (m_data.point_2 (pvertex, m_min_time), point));
FT time = dist / m_data.speed(pvertex);
m_queue.push (Event (pvertex, iedge, m_min_time + time));
}
}
return true;
}
void run()
{
CGAL_KSR_CERR(1) << "Unstacking queue" << std::endl;
@ -421,10 +481,6 @@ private:
FT current_time = ev.time();
m_data.update_positions (current_time);
CGAL_KSR_CERR(2) << "* Applying " << iter << ": " << ev << std::endl;
if (iter < 10)
{
dump (m_data, "iter_0" + std::to_string(iter));
@ -436,10 +492,20 @@ private:
dump_event (m_data, ev, "iter_" + std::to_string(iter));
}
m_data.update_positions (current_time);
CGAL_KSR_CERR(2) << "* Applying " << iter << ": " << ev << std::endl;
m_data.update_positions (current_time + 0.01);
dump (m_data, "shifted_" + std::to_string(iter));
m_data.update_positions (current_time);
++ iter;
if (iter == 5)
if (iter == 27)
{
exit(0);
}
apply(ev);
@ -450,95 +516,110 @@ private:
void apply (const Event& ev)
{
PVertex pvertex = ev.pvertex();
IEdge iedge = ev.iedge();
}
#if 0
void transfer_events (KSR::size_t old_vertex, KSR::size_t new_vertex)
{
CGAL_KSR_CERR(3) << "** Transfering events of vertex " << old_vertex << " to " << new_vertex << std::endl;
KSR::vector<Event> events;
m_queue.erase_vertex_events (old_vertex, events);
for (Event& ev : events)
if (ev.is_pvertex_to_pvertex())
{
ev.vertex_idx() = new_vertex;
CGAL_KSR_CERR(4) << "**** - Pushing " << ev << std::endl;
m_queue.push (ev);
PVertex pother = ev.pother();
remove_events (pvertex);
remove_events (pother);
CGAL_assertion (m_data.has_iedge(pvertex));
if (m_data.has_iedge(pother)) // Two constrained vertices meet
{
CGAL_assertion_msg (false, "TODO: two constrained");
}
else // One constrained vertex meets a free vertex
{
m_data.transfer_vertex (pvertex, pother);
compute_events_of_vertices (std::array<PVertex,2>{pvertex, pother});
}
}
else if (ev.is_pvertex_to_iedge())
{
remove_events (pvertex);
IEdge iedge = ev.iedge();
PFace pface = m_data.pface_of_pvertex (pvertex);
bool collision, bbox_reached;
std::tie (collision, bbox_reached)
= m_data.collision_occured (pvertex, iedge);
if (collision && m_data.k(pface) > 1)
m_data.k(pface) --;
if (bbox_reached)
m_data.k(pface) = 1;
if (m_data.k(pface) == 1) // Polygon stops
{
PVertex pvnew = m_data.crop_polygon (pvertex, iedge);
compute_events_of_vertices (std::array<PVertex,2>{pvertex, pvnew});
}
else // Polygon continues beyond the edge
{
std::array<PVertex, 3> pvnew = m_data.propagate_polygon (pvertex, iedge);
compute_events_of_vertices (std::array<PVertex,3>{pvnew[0], pvnew[1], pvnew[2]});
}
}
else if (ev.is_pvertex_to_ivertex())
{
// first, let's gather all vertices that will get merged
std::vector<PVertex> pvertices
= m_data.pvertices_around_ivertex (ev.pvertex(), ev.ivertex());
CGAL_assertion_msg (pvertices.size() > 1, "Isolated PVertex reaching an IVertex");
std::cerr << "Found " << pvertices.size() << " pvertices ready to be merged" << std::endl;
// Remove associated events
for (const PVertex pvertex : pvertices)
remove_events (pvertex);
// Merge them and get the newly created vertices
std::vector<PVertex> new_pvertices
= m_data.merge_pvertices_on_ivertex (pvertices, ev.ivertex());
// And compute new events
compute_events_of_vertices (new_pvertices);
}
else
{
CGAL_assertion_msg (false, "Event is invalid");
}
}
void update_events (KSR::size_t vertex_idx)
void remove_events (const PVertex& pvertex)
{
remove_events (vertex_idx);
compute_new_events (vertex_idx);
m_queue.erase_vertex_events (pvertex);
}
void remove_events (KSR::size_t vertex_idx)
template <typename PVertexRange>
void compute_events_of_vertices (const PVertexRange& pvertices)
{
CGAL_KSR_CERR(3) << "** Removing events of vertex " << vertex_idx << std::endl;
m_queue.erase_vertex_events (vertex_idx);
}
void compute_new_events (KSR::size_t vertex_idx)
{
const Vertex& vertex = m_data.vertex (vertex_idx);
if (vertex.is_frozen())
return;
CGAL_KSR_CERR(3) << "** Computing new events of vertex " << vertex_idx << std::endl;
FT current_time = m_data.current_time();
// TODO
m_min_time = m_data.current_time();
m_data.update_positions(m_max_time);
KSR::size_t support_plane_idx = m_data.polygon_of_vertex(vertex_idx).support_plane_idx();
const Support_plane& support_plane = m_data.support_plane(support_plane_idx);
// Precompute segments and bboxes
KSR::vector<IEdge> iedges;
KSR::vector<Segment_2> segments_2;
segments_2.reserve (support_plane.intersection_lines_idx().size());
KSR::vector<CGAL::Bbox_2> segment_bboxes;
segment_bboxes.reserve (support_plane.intersection_lines_idx().size());
for (KSR::size_t intersection_line_idx : support_plane.intersection_lines_idx())
{
segments_2.push_back (m_data.segment_of_intersection_line_on_support_plane (intersection_line_idx, support_plane_idx));
segment_bboxes.push_back (segments_2.back().bbox());
}
init_search_structures (pvertices.front().first, iedges, segments_2, segment_bboxes);
for (const PVertex& pvertex : pvertices)
m_data.deactivate(pvertex);
Segment_2 si (vertex.point (current_time), vertex.point (m_max_time));
CGAL::Bbox_2 si_bbox = si.bbox();
for (std::size_t j = 0; j < segments_2.size(); ++ j)
{
KSR::size_t intersection_line_idx = support_plane.intersection_lines_idx()[j];
if (m_data.intersection_line_idx_of_vertex(vertex_idx) == intersection_line_idx)
continue;
if (!CGAL::do_overlap (si_bbox, segment_bboxes[j]))
continue;
Point_2 point;
if (!KSR::intersection_2 (si, segments_2[j], point))
continue;
FT dist = CGAL::approximate_sqrt (CGAL::squared_distance (vertex.point (current_time), point));
FT time = dist / vertex.speed();
m_queue.push (Event (vertex_idx, intersection_line_idx, current_time + time));
}
m_data.update_positions(current_time);
for (const PVertex& pvertex : pvertices)
compute_events_of_vertex (pvertex, iedges, segments_2, segment_bboxes);
for (const PVertex& pvertex : pvertices)
m_data.activate(pvertex);
m_data.update_positions(m_min_time);
}
void get_meta_neighbors (KSR::vector<KSR::vector<KSR::size_t> >& neighbors) const
{
}
#endif
};

View File

@ -473,7 +473,7 @@ private: //-------------------------------------------------- connectivity types
/// \sa `Halfedge_connectivity`, `Face_connectivity`
struct Vertex_connectivity
{
/// an incoming halfedge per vertex (it will be a border halfedge for border vertices)
/// an incoming halfedge per vlertex (it will be a border halfedge for border vertices)
Halfedge_index halfedge_;
};