mirror of https://github.com/CGAL/cgal
1528 lines
55 KiB
C++
1528 lines
55 KiB
C++
// Copyright (c) 2019 GeometryFactory Sarl (France).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org).
|
|
// 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.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
// SPDX-License-Identifier: GPL-3.0+
|
|
//
|
|
// Author(s) : Simon Giraudot
|
|
|
|
#ifndef CGAL_KSR_3_DATA_STRUCTURE_H
|
|
#define CGAL_KSR_3_DATA_STRUCTURE_H
|
|
|
|
//#include <CGAL/license/Kinetic_shape_reconstruction.h>
|
|
|
|
#include <queue>
|
|
|
|
#include <boost/function_output_iterator.hpp>
|
|
|
|
#include <CGAL/KSR/utils.h>
|
|
#include <CGAL/KSR/verbosity.h>
|
|
#include <CGAL/KSR/debug.h>
|
|
|
|
#include <CGAL/KSR_3/Support_plane.h>
|
|
#include <CGAL/KSR_3/Intersection_graph.h>
|
|
|
|
#include <CGAL/Polygon_2.h>
|
|
#include <CGAL/centroid.h>
|
|
|
|
namespace CGAL
|
|
{
|
|
|
|
namespace KSR_3
|
|
{
|
|
|
|
template <typename GeomTraits>
|
|
class Data_structure
|
|
{
|
|
public:
|
|
|
|
typedef GeomTraits Kernel;
|
|
|
|
private:
|
|
|
|
typedef typename Kernel::FT FT;
|
|
typedef typename Kernel::Point_2 Point_2;
|
|
typedef typename Kernel::Vector_2 Vector_2;
|
|
typedef typename Kernel::Segment_2 Segment_2;
|
|
typedef typename Kernel::Ray_2 Ray_2;
|
|
typedef typename Kernel::Line_2 Line_2;
|
|
typedef typename Kernel::Direction_2 Direction_2;
|
|
typedef typename Kernel::Point_3 Point_3;
|
|
typedef typename Kernel::Vector_3 Vector_3;
|
|
typedef typename Kernel::Segment_3 Segment_3;
|
|
typedef typename Kernel::Plane_3 Plane_3;
|
|
typedef typename Kernel::Line_3 Line_3;
|
|
|
|
typedef KSR_3::Support_plane<Kernel> Support_plane;
|
|
typedef typename Support_plane::Mesh Mesh;
|
|
typedef typename Mesh::Vertex_index Vertex_index;
|
|
typedef typename Mesh::Face_index Face_index;
|
|
typedef typename Mesh::Edge_index Edge_index;
|
|
typedef typename Mesh::Halfedge_index Halfedge_index;
|
|
|
|
typedef KSR_3::Intersection_graph<Kernel> Intersection_graph;
|
|
|
|
typedef KSR::vector<Support_plane> Support_planes;
|
|
|
|
public:
|
|
|
|
typedef std::pair<KSR::size_t, Vertex_index> PVertex;
|
|
typedef std::pair<KSR::size_t, Edge_index> PEdge;
|
|
typedef std::pair<KSR::size_t, Face_index> PFace;
|
|
|
|
template <typename PSimplex>
|
|
struct Make_PSimplex
|
|
{
|
|
typedef typename PSimplex::second_type argument_type;
|
|
typedef PSimplex result_type;
|
|
KSR::size_t support_plane_idx;
|
|
|
|
Make_PSimplex (KSR::size_t support_plane_idx) : support_plane_idx (support_plane_idx) { }
|
|
|
|
result_type operator() (const argument_type& arg) const
|
|
{
|
|
return result_type(support_plane_idx, arg);
|
|
}
|
|
};
|
|
|
|
typedef boost::transform_iterator<Make_PSimplex<PVertex>,
|
|
typename Mesh::Vertex_range::iterator> PVertex_iterator;
|
|
typedef boost::transform_iterator<Make_PSimplex<PEdge>,
|
|
typename Mesh::Edge_range::iterator> PEdge_iterator;
|
|
typedef boost::transform_iterator<Make_PSimplex<PFace>,
|
|
typename Mesh::Face_range::iterator> PFace_iterator;
|
|
|
|
typedef Iterator_range<PVertex_iterator> PVertices;
|
|
typedef Iterator_range<PEdge_iterator> PEdges;
|
|
typedef Iterator_range<PFace_iterator> PFaces;
|
|
|
|
struct Halfedge_to_pvertex
|
|
{
|
|
typedef Halfedge_index argument_type;
|
|
typedef PVertex result_type;
|
|
KSR::size_t support_plane_idx;
|
|
const Mesh& mesh;
|
|
|
|
Halfedge_to_pvertex (KSR::size_t support_plane_idx, const Mesh& mesh)
|
|
: support_plane_idx (support_plane_idx), mesh (mesh) { }
|
|
|
|
result_type operator() (const argument_type& arg) const
|
|
{
|
|
return result_type(support_plane_idx, mesh.target(arg));
|
|
}
|
|
};
|
|
|
|
typedef boost::transform_iterator<Halfedge_to_pvertex,
|
|
Halfedge_around_face_iterator<Mesh> > PVertex_of_pface_iterator;
|
|
typedef Iterator_range<PVertex_of_pface_iterator> PVertices_of_pface;
|
|
|
|
struct Halfedge_to_pedge
|
|
{
|
|
typedef Halfedge_index argument_type;
|
|
typedef PEdge result_type;
|
|
KSR::size_t support_plane_idx;
|
|
const Mesh& mesh;
|
|
|
|
Halfedge_to_pedge (KSR::size_t support_plane_idx, const Mesh& mesh)
|
|
: support_plane_idx (support_plane_idx), mesh (mesh) { }
|
|
|
|
result_type operator() (const argument_type& arg) const
|
|
{
|
|
return result_type(support_plane_idx, mesh.edge(arg));
|
|
}
|
|
};
|
|
|
|
typedef boost::transform_iterator<Halfedge_to_pedge,
|
|
Halfedge_around_target_iterator<Mesh> > PEdge_around_pvertex_iterator;
|
|
typedef Iterator_range<PEdge_around_pvertex_iterator> PEdges_around_pvertex;
|
|
|
|
typedef typename Intersection_graph::Vertex_descriptor IVertex;
|
|
typedef typename Intersection_graph::Edge_descriptor IEdge;
|
|
typedef typename Intersection_graph::Vertices IVertices;
|
|
typedef typename Intersection_graph::Edges IEdges;
|
|
typedef typename Intersection_graph::Incident_edges Incident_iedges;
|
|
|
|
private:
|
|
|
|
// Main data structure
|
|
Support_planes m_support_planes;
|
|
Intersection_graph m_intersection_graph;
|
|
|
|
// Helping data structures
|
|
std::map<Point_3, KSR::size_t> m_meta_map;
|
|
|
|
FT m_current_time;
|
|
|
|
public:
|
|
|
|
Data_structure()
|
|
: m_current_time(0)
|
|
{ }
|
|
|
|
void print() const
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
void init (std::size_t number_of_polygons)
|
|
{
|
|
m_support_planes.reserve (number_of_polygons + 6);
|
|
}
|
|
|
|
const FT& current_time() const { return m_current_time; }
|
|
|
|
/*******************************
|
|
* Support planes
|
|
*******************************/
|
|
|
|
KSR::size_t number_of_support_planes() const { return m_support_planes.size(); }
|
|
|
|
bool is_bbox_support_plane (KSR::size_t support_plane_idx) const
|
|
{ return (support_plane_idx < 6); }
|
|
|
|
bool mesh_is_valid (KSR::size_t support_plane_idx) const
|
|
{
|
|
bool is_valid = mesh(support_plane_idx).is_valid();
|
|
if (!is_valid)
|
|
return false;
|
|
|
|
for (PFace pface : pfaces(support_plane_idx))
|
|
{
|
|
std::function<Point_2(PVertex)> unary_f = [&](const PVertex& pvertex) -> Point_2 { return point_2(pvertex); };
|
|
CGAL::Polygon_2<Kernel> polygon
|
|
(boost::make_transform_iterator
|
|
(pvertices_of_pface(pface).begin(), unary_f),
|
|
boost::make_transform_iterator
|
|
(pvertices_of_pface(pface).end(), unary_f));
|
|
|
|
// if (!polygon.is_simple())
|
|
// {
|
|
// std::cerr << "PFace(" << pface.first << ":" << pface.second << ") is not simple" << std::endl;
|
|
// for (const Point_2& p : polygon)
|
|
// std::cerr << to_3d(support_plane_idx,p) << " ";
|
|
// std::cerr << to_3d(support_plane_idx,polygon[0]) << " ";
|
|
// std::cerr << std::endl;
|
|
// return false;
|
|
// }
|
|
if (!polygon.is_convex())
|
|
{
|
|
std::cerr << "PFace(" << pface.first << ":" << pface.second << ") is not convex" << std::endl;
|
|
for (const Point_2& p : polygon)
|
|
std::cerr << to_3d(support_plane_idx,p) << " ";
|
|
std::cerr << to_3d(support_plane_idx,polygon[0]) << " ";
|
|
std::cerr << std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
KSR::size_t add_support_plane (const Support_plane& new_support_plane)
|
|
{
|
|
KSR::size_t support_plane_idx = KSR::no_element();
|
|
for (KSR::size_t i = 0; i < number_of_support_planes(); ++ i)
|
|
if (new_support_plane == support_plane(i))
|
|
{
|
|
support_plane_idx = i;
|
|
break;
|
|
}
|
|
|
|
if (support_plane_idx == KSR::no_element())
|
|
{
|
|
support_plane_idx = number_of_support_planes();
|
|
m_support_planes.push_back (new_support_plane);
|
|
}
|
|
|
|
if (support_plane_idx >= 6) // Intersect planes with bbox...
|
|
{
|
|
std::vector<std::pair<IEdge, Point_3> > intersections;
|
|
|
|
Point_3 centroid;
|
|
for (const IEdge& edge : m_intersection_graph.edges())
|
|
{
|
|
Point_3 point;
|
|
if (!KSR::intersection_3 (support_plane(support_plane_idx).plane(),
|
|
m_intersection_graph.segment_3 (edge), point))
|
|
continue;
|
|
|
|
centroid = CGAL::barycenter (centroid, intersections.size(), point, 1);
|
|
intersections.push_back (std::make_pair (edge, point));
|
|
}
|
|
|
|
Point_2 centroid_2 = support_plane(support_plane_idx).to_2d (centroid);
|
|
std::sort (intersections.begin(), intersections.end(),
|
|
[&] (const std::pair<IEdge, Point_3>& a,
|
|
const std::pair<IEdge, Point_3>& b) -> bool
|
|
{
|
|
return (Direction_2 (Segment_2 (centroid_2, support_plane(support_plane_idx).to_2d (a.second)))
|
|
< Direction_2 (Segment_2 (centroid_2, support_plane(support_plane_idx).to_2d (b.second))));
|
|
});
|
|
|
|
KSR::vector<KSR::size_t> common_planes_idx;
|
|
std::map<KSR::size_t, KSR::size_t> map_lines_idx;
|
|
KSR::vector<IVertex> vertices;
|
|
vertices.reserve (intersections.size());
|
|
for (std::size_t i = 0; i < intersections.size(); ++ i)
|
|
{
|
|
const IEdge& e0 = intersections[i].first;
|
|
const IEdge& e1 = intersections[(i+1)%intersections.size()].first;
|
|
|
|
KSR::size_t common_plane_idx = KSR::no_element();
|
|
std::set_intersection (m_intersection_graph.intersected_planes(e0).begin(),
|
|
m_intersection_graph.intersected_planes(e0).end(),
|
|
m_intersection_graph.intersected_planes(e1).begin(),
|
|
m_intersection_graph.intersected_planes(e1).end(),
|
|
boost::make_function_output_iterator
|
|
([&](const KSR::size_t& idx) -> void
|
|
{
|
|
if (idx < 6)
|
|
{
|
|
CGAL_assertion (common_plane_idx == KSR::no_element());
|
|
common_plane_idx = idx;
|
|
}
|
|
}));
|
|
CGAL_assertion (common_plane_idx != KSR::no_element());
|
|
common_planes_idx.push_back (common_plane_idx);
|
|
|
|
typename std::map<KSR::size_t, KSR::size_t>::iterator iter;
|
|
bool inserted;
|
|
std::tie (iter, inserted)
|
|
= map_lines_idx.insert (std::make_pair (common_plane_idx, KSR::no_element()));
|
|
if (inserted)
|
|
iter->second = m_intersection_graph.add_line();
|
|
|
|
vertices.push_back (m_intersection_graph.add_vertex (intersections[i].second).first);
|
|
}
|
|
|
|
for (std::size_t i = 0; i < intersections.size(); ++ i)
|
|
{
|
|
for (KSR::size_t sp_idx : m_intersection_graph.intersected_planes(intersections[i].first))
|
|
support_plane(sp_idx).iedges().erase (intersections[i].first);
|
|
IEdge edge_0, edge_1;
|
|
std::tie (edge_0, edge_1)
|
|
= m_intersection_graph.split_edge (intersections[i].first, vertices[i]);
|
|
for (const IEdge& edge : { edge_0, edge_1 })
|
|
for (KSR::size_t sp_idx : m_intersection_graph.intersected_planes(edge))
|
|
support_plane(sp_idx).iedges().insert (edge);
|
|
|
|
IEdge new_edge =
|
|
m_intersection_graph.add_edge (vertices[i], vertices[(i+1)%vertices.size()], support_plane_idx).first;
|
|
m_intersection_graph.intersected_planes(new_edge).insert (common_planes_idx[i]);
|
|
m_intersection_graph.set_line (new_edge, map_lines_idx[common_planes_idx[i]]);
|
|
|
|
support_plane(support_plane_idx).iedges().insert (new_edge);
|
|
support_plane(common_planes_idx[i]).iedges().insert (new_edge);
|
|
}
|
|
}
|
|
|
|
return support_plane_idx;
|
|
}
|
|
|
|
void add_bbox_polygon (const std::array<Point_3, 4>& polygon)
|
|
{
|
|
KSR::size_t support_plane_idx = add_support_plane (Support_plane (polygon));
|
|
|
|
std::array<IVertex, 4> ivertices;
|
|
std::array<Point_2, 4> points;
|
|
for (std::size_t i = 0; i < 4; ++ i)
|
|
{
|
|
points[i] = support_plane(support_plane_idx).to_2d(polygon[i]);
|
|
ivertices[i] = m_intersection_graph.add_vertex(polygon[i]).first;
|
|
}
|
|
|
|
std::array<Vertex_index, 4> vertices
|
|
= support_plane(support_plane_idx).add_bbox_polygon (points, ivertices);
|
|
|
|
for (std::size_t i = 0; i < 4; ++ i)
|
|
{
|
|
IEdge iedge;
|
|
bool inserted;
|
|
std::tie (iedge, inserted)
|
|
= m_intersection_graph.add_edge (ivertices[i], ivertices[(i+1)%4], support_plane_idx);
|
|
if (inserted)
|
|
m_intersection_graph.set_line (iedge, m_intersection_graph.add_line());
|
|
|
|
support_plane(support_plane_idx).set_iedge
|
|
(vertices[i], vertices[(i+1)%4], iedge);
|
|
|
|
support_plane(support_plane_idx).iedges().insert (iedge);
|
|
}
|
|
}
|
|
|
|
template <typename PointRange>
|
|
void add_polygon (const PointRange& polygon, KSR::size_t input_idx)
|
|
{
|
|
KSR::size_t support_plane_idx = add_support_plane (Support_plane (polygon));
|
|
|
|
// Create ordered polygon
|
|
std::vector<Point_2> points;
|
|
points.reserve (polygon.size());
|
|
for (const Point_3& p : polygon)
|
|
points.push_back (support_plane(support_plane_idx).to_2d(p));
|
|
|
|
Point_2 centroid = CGAL::centroid (points.begin(), points.end());
|
|
|
|
std::sort (points.begin(), points.end(),
|
|
[&](const Point_2& a, const Point_2& b) -> bool
|
|
{
|
|
return (Direction_2 (Segment_2 (centroid, a))
|
|
< Direction_2 (Segment_2 (centroid, b)));
|
|
});
|
|
|
|
support_plane(support_plane_idx).add_polygon (points, centroid, input_idx);
|
|
}
|
|
|
|
/*******************************
|
|
* PSimplices
|
|
*******************************/
|
|
|
|
static PVertex null_pvertex() { return PVertex(KSR::no_element(), Vertex_index()); }
|
|
static PEdge null_pedge() { return PEdge(KSR::no_element(), Edge_index()); }
|
|
static PFace null_pface() { return PFace(KSR::no_element(), Face_index()); }
|
|
|
|
PVertices pvertices (KSR::size_t support_plane_idx) const
|
|
{
|
|
return PVertices (boost::make_transform_iterator
|
|
(mesh(support_plane_idx).vertices().begin(),
|
|
Make_PSimplex<PVertex>(support_plane_idx)),
|
|
boost::make_transform_iterator
|
|
(mesh(support_plane_idx).vertices().end(),
|
|
Make_PSimplex<PVertex>(support_plane_idx)));
|
|
|
|
}
|
|
|
|
PEdges pedges (KSR::size_t support_plane_idx) const
|
|
{
|
|
return PEdges (boost::make_transform_iterator
|
|
(mesh(support_plane_idx).edges().begin(),
|
|
Make_PSimplex<PEdge>(support_plane_idx)),
|
|
boost::make_transform_iterator
|
|
(mesh(support_plane_idx).edges().end(),
|
|
Make_PSimplex<PEdge>(support_plane_idx)));
|
|
|
|
}
|
|
|
|
PFaces pfaces (KSR::size_t support_plane_idx) const
|
|
{
|
|
return PFaces (boost::make_transform_iterator
|
|
(mesh(support_plane_idx).faces().begin(),
|
|
Make_PSimplex<PFace>(support_plane_idx)),
|
|
boost::make_transform_iterator
|
|
(mesh(support_plane_idx).faces().end(),
|
|
Make_PSimplex<PFace>(support_plane_idx)));
|
|
|
|
}
|
|
|
|
// Get prev and next of free vertex
|
|
PVertex prev (const PVertex& pvertex) const
|
|
{
|
|
return PVertex (pvertex.first, support_plane(pvertex).prev(pvertex.second));
|
|
}
|
|
PVertex next (const PVertex& pvertex) const
|
|
{
|
|
return PVertex (pvertex.first, support_plane(pvertex).next(pvertex.second));
|
|
}
|
|
|
|
// Get prev and next of constrained vertex
|
|
std::pair<PVertex, PVertex> prev_and_next (const PVertex& pvertex) const
|
|
{
|
|
std::pair<PVertex, PVertex> out (null_pvertex(), null_pvertex());
|
|
|
|
for (Halfedge_index hi : halfedges_around_target(halfedge(pvertex.second, mesh(pvertex)), mesh(pvertex)))
|
|
{
|
|
IEdge iedge = support_plane(pvertex).iedge (mesh(pvertex).edge(hi));
|
|
if (iedge == this->iedge(pvertex))
|
|
continue;
|
|
if (out.first == null_pvertex())
|
|
out.first = PVertex (pvertex.first, mesh(pvertex).source(hi));
|
|
else
|
|
{
|
|
out.second = PVertex (pvertex.first, mesh(pvertex).source(hi));
|
|
return out;
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
std::pair<PVertex, PVertex> border_prev_and_next (const PVertex& pvertex) const
|
|
{
|
|
Halfedge_index hi = mesh(pvertex).halfedge(pvertex.second);
|
|
if (mesh(pvertex).face(hi) != Face_index())
|
|
hi = mesh(pvertex).prev (mesh(pvertex).opposite(hi));
|
|
|
|
CGAL_assertion (mesh(pvertex).face(hi) == Face_index());
|
|
return std::make_pair (PVertex (pvertex.first, mesh(pvertex).source (hi)),
|
|
PVertex (pvertex.first, mesh(pvertex).target (mesh(pvertex).next(hi))));
|
|
}
|
|
|
|
PVertex add_pvertex (KSR::size_t support_plane_idx, const Point_2& point)
|
|
{
|
|
return PVertex (support_plane_idx, mesh(support_plane_idx).add_vertex(point));
|
|
}
|
|
|
|
template <typename VertexRange>
|
|
PFace add_pface (const VertexRange& pvertices)
|
|
{
|
|
return PFace (pvertices.front().first,
|
|
mesh(pvertices.front()).add_face
|
|
(CGAL::make_range
|
|
(boost::make_transform_iterator
|
|
(pvertices.begin(),
|
|
CGAL::Property_map_to_unary_function
|
|
<CGAL::Second_of_pair_property_map<PVertex> >()),
|
|
boost::make_transform_iterator
|
|
(pvertices.end(),
|
|
CGAL::Property_map_to_unary_function
|
|
<CGAL::Second_of_pair_property_map<PVertex> >()))));
|
|
}
|
|
|
|
void clear_polygon_faces (KSR::size_t support_plane_idx)
|
|
{
|
|
Mesh& m = mesh(support_plane_idx);
|
|
for (Face_index fi : m.faces())
|
|
m.remove_face(fi);
|
|
for (Edge_index ei : m.edges())
|
|
m.remove_edge(ei);
|
|
for (Vertex_index vi : m.vertices())
|
|
m.set_halfedge(vi, Halfedge_index());
|
|
}
|
|
|
|
PVertex source (const PEdge& pedge) const
|
|
{ return PVertex (pedge.first, mesh(pedge).source(mesh(pedge).halfedge(pedge.second))); }
|
|
PVertex target (const PEdge& pedge) const
|
|
{ return PVertex (pedge.first, mesh(pedge).target(mesh(pedge).halfedge(pedge.second))); }
|
|
PVertex opposite (const PEdge& pedge, const PVertex& pvertex) const
|
|
{
|
|
if (mesh(pedge).target(mesh(pedge).halfedge(pedge.second)) == pvertex.second)
|
|
return PVertex (pedge.first, mesh(pedge).source(mesh(pedge).halfedge(pedge.second)));
|
|
|
|
CGAL_assertion (mesh(pedge).source(mesh(pedge).halfedge(pedge.second)) == pvertex.second);
|
|
return PVertex (pedge.first, mesh(pedge).target(mesh(pedge).halfedge(pedge.second)));
|
|
}
|
|
|
|
PFace pface_of_pvertex (const PVertex& pvertex) const
|
|
{
|
|
return PFace (pvertex.first, support_plane(pvertex).face (pvertex.second));
|
|
}
|
|
|
|
std::pair<PFace, PFace> pfaces_of_pvertex (const PVertex& pvertex) const
|
|
{
|
|
std::pair<PFace, PFace> out (null_pface(), null_pface());
|
|
|
|
std::tie (out.first.second, out.second.second)
|
|
= support_plane(pvertex).faces (pvertex.second);
|
|
|
|
if (out.first.second != Face_index())
|
|
out.first.first = pvertex.first;
|
|
if (out.second.second != Face_index())
|
|
out.second.first = pvertex.first;
|
|
return out;
|
|
}
|
|
|
|
PVertices_of_pface pvertices_of_pface (const PFace& pface) const
|
|
{
|
|
return PVertices_of_pface (boost::make_transform_iterator
|
|
(halfedges_around_face(halfedge(pface.second, mesh(pface)),
|
|
mesh(pface)).begin(),
|
|
Halfedge_to_pvertex(pface.first, mesh(pface))),
|
|
boost::make_transform_iterator
|
|
(halfedges_around_face(halfedge(pface.second, mesh(pface)),
|
|
mesh(pface)).end(),
|
|
Halfedge_to_pvertex(pface.first, mesh(pface))));
|
|
}
|
|
|
|
PEdges_around_pvertex pedges_around_pvertex (const PVertex& pvertex) const
|
|
{
|
|
return PEdges_around_pvertex (boost::make_transform_iterator
|
|
(halfedges_around_target(halfedge(pvertex.second, mesh(pvertex)),
|
|
mesh(pvertex)).begin(),
|
|
Halfedge_to_pedge(pvertex.first, mesh(pvertex))),
|
|
boost::make_transform_iterator
|
|
(halfedges_around_target(halfedge(pvertex.second, mesh(pvertex)),
|
|
mesh(pvertex)).end(),
|
|
Halfedge_to_pedge(pvertex.first, mesh(pvertex))));
|
|
}
|
|
|
|
const KSR::size_t& input (const PFace& pface) const
|
|
{ return support_plane(pface).input(pface.second); }
|
|
KSR::size_t& input (const PFace& pface)
|
|
{ return support_plane(pface).input(pface.second); }
|
|
|
|
const unsigned int& k (const PFace& pface) const
|
|
{ return support_plane(pface).k(pface.second); }
|
|
unsigned int& k (const PFace& pface)
|
|
{ return support_plane(pface).k(pface.second); }
|
|
|
|
bool is_frozen (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).is_frozen (pvertex.second); }
|
|
const Vector_2& direction (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).direction (pvertex.second); }
|
|
Vector_2& direction (const PVertex& pvertex)
|
|
{ return support_plane(pvertex).direction (pvertex.second); }
|
|
FT speed (const PVertex& pvertex)
|
|
{ return support_plane(pvertex).speed (pvertex.second); }
|
|
|
|
void freeze (PVertex& pvertex)
|
|
{
|
|
Point_2 p = point_2 (pvertex, m_current_time);
|
|
support_plane(pvertex).direction (pvertex.second) = CGAL::NULL_VECTOR;
|
|
support_plane(pvertex).set_point (pvertex.second, p);
|
|
}
|
|
|
|
bool is_active (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).is_active (pvertex.second); }
|
|
|
|
void deactivate (const PVertex& pvertex)
|
|
{
|
|
support_plane(pvertex).set_active (pvertex.second, false);
|
|
if (iedge(pvertex) != null_iedge())
|
|
m_intersection_graph.is_active(iedge(pvertex)) = false;
|
|
if (ivertex(pvertex) != null_ivertex())
|
|
{
|
|
m_intersection_graph.is_active(ivertex(pvertex)) = false;
|
|
std::cerr << str(ivertex(pvertex)) << " deactivated" << std::endl;
|
|
}
|
|
}
|
|
void activate (const PVertex& pvertex)
|
|
{
|
|
support_plane(pvertex).set_active (pvertex.second, true);
|
|
if (iedge(pvertex) != null_iedge())
|
|
m_intersection_graph.is_active(iedge(pvertex)) = true;
|
|
if (ivertex(pvertex) != null_ivertex())
|
|
{
|
|
m_intersection_graph.is_active(ivertex(pvertex)) = true;
|
|
std::cerr << str(ivertex(pvertex)) << " activated" << std::endl;
|
|
}
|
|
}
|
|
|
|
/*******************************
|
|
* ISimplices
|
|
*******************************/
|
|
|
|
static IVertex null_ivertex() { return Intersection_graph::null_ivertex(); }
|
|
static IEdge null_iedge() { return Intersection_graph::null_iedge(); }
|
|
|
|
IVertices ivertices() const { return m_intersection_graph.vertices(); }
|
|
IEdges iedges() const { return m_intersection_graph.edges(); }
|
|
|
|
KSR::size_t nb_intersection_lines() const { return m_intersection_graph.nb_lines(); }
|
|
KSR::size_t line_idx (const IEdge& iedge) const { return m_intersection_graph.line (iedge); }
|
|
KSR::size_t line_idx (const PVertex& pvertex) const { return line_idx (iedge(pvertex)); }
|
|
|
|
IVertex add_ivertex (const Point_3& point, const KSR::Idx_set& support_planes_idx)
|
|
{
|
|
KSR::Idx_vector vec_planes;
|
|
std::copy (support_planes_idx.begin(), support_planes_idx.end(),
|
|
std::back_inserter (vec_planes));
|
|
|
|
IVertex vertex;
|
|
bool inserted;
|
|
std::tie (vertex, inserted) = m_intersection_graph.add_vertex (point, vec_planes);
|
|
return vertex;
|
|
}
|
|
|
|
void add_iedge (const KSR::Idx_set& support_planes_idx,
|
|
KSR::vector<IVertex>& vertices)
|
|
{
|
|
Point_3 source = m_intersection_graph.point_3 (vertices.front());
|
|
|
|
std::sort (vertices.begin(), vertices.end(),
|
|
[&](const IVertex& a, const IVertex& b) -> bool
|
|
{
|
|
return (CGAL::squared_distance (source, m_intersection_graph.point_3(a))
|
|
< CGAL::squared_distance (source, m_intersection_graph.point_3(b)));
|
|
});
|
|
|
|
KSR::size_t line_idx = m_intersection_graph.add_line();
|
|
|
|
for (KSR::size_t i = 0; i < vertices.size() - 1; ++ i)
|
|
{
|
|
IEdge iedge;
|
|
bool inserted;
|
|
std::tie (iedge, inserted)
|
|
= m_intersection_graph.add_edge (vertices[i],
|
|
vertices[i+1],
|
|
support_planes_idx);
|
|
CGAL_assertion (inserted);
|
|
m_intersection_graph.set_line (iedge, line_idx);
|
|
|
|
for (KSR::size_t support_plane_idx : support_planes_idx)
|
|
support_plane(support_plane_idx).iedges().insert (iedge);
|
|
}
|
|
}
|
|
|
|
IVertex source (const IEdge& edge) const
|
|
{ return m_intersection_graph.source (edge); }
|
|
IVertex target (const IEdge& edge) const
|
|
{ return m_intersection_graph.target (edge); }
|
|
IVertex opposite (const IEdge& edge, const IVertex& ivertex) const
|
|
{
|
|
IVertex out = source (edge);
|
|
if (out == ivertex)
|
|
return target (edge);
|
|
CGAL_assertion (target(edge) == ivertex);
|
|
return out;
|
|
}
|
|
|
|
Incident_iedges incident_iedges (const IVertex& ivertex) const
|
|
{ return m_intersection_graph.incident_edges(ivertex); }
|
|
|
|
const std::set<IEdge>& iedges (KSR::size_t support_plane_idx) const
|
|
{ return support_plane(support_plane_idx).iedges(); }
|
|
|
|
const KSR::Idx_set& intersected_planes (const IEdge& iedge) const
|
|
{ return m_intersection_graph.intersected_planes(iedge); }
|
|
|
|
KSR::Idx_set intersected_planes (const IVertex& ivertex, bool keep_bbox = true) const
|
|
{
|
|
KSR::Idx_set out;
|
|
for (const IEdge& incident_iedge : incident_iedges (ivertex))
|
|
for (KSR::size_t support_plane_idx : intersected_planes (incident_iedge))
|
|
{
|
|
if (!keep_bbox && support_plane_idx < 6)
|
|
continue;
|
|
out.insert (support_plane_idx);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
bool is_active (const IEdge& iedge) const
|
|
{ return m_intersection_graph.is_active (iedge); }
|
|
bool is_active (const IVertex& ivertex) const
|
|
{ return m_intersection_graph.is_active (ivertex); }
|
|
|
|
bool is_bbox_iedge (const IEdge& edge) const
|
|
{
|
|
for (KSR::size_t support_plane_idx : m_intersection_graph.intersected_planes(edge))
|
|
if (support_plane_idx < 6)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*******************************
|
|
* Connectivity
|
|
*******************************/
|
|
|
|
bool has_ivertex (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).has_ivertex(pvertex.second); }
|
|
IVertex ivertex (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).ivertex(pvertex.second); }
|
|
|
|
bool has_iedge (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).has_iedge(pvertex.second); }
|
|
IEdge iedge (const PVertex& pvertex) const
|
|
{ return support_plane(pvertex).iedge(pvertex.second); }
|
|
|
|
bool has_iedge (const PEdge& pedge) const
|
|
{ return support_plane(pedge).has_iedge(pedge.second); }
|
|
IEdge iedge (const PEdge& pedge) const
|
|
{ return support_plane(pedge).iedge(pedge.second); }
|
|
|
|
|
|
void connect (const PVertex& pvertex, const IVertex& ivertex)
|
|
{ support_plane(pvertex).set_ivertex (pvertex.second, ivertex); }
|
|
void connect (const PVertex& pvertex, const IEdge& iedge)
|
|
{ support_plane(pvertex).set_iedge (pvertex.second, iedge); }
|
|
void connect (const PVertex& a, const PVertex& b, const IEdge& iedge)
|
|
{ support_plane(a).set_iedge (a.second, b.second, iedge); }
|
|
void connect (const PEdge& pedge, const IEdge& iedge)
|
|
{ support_plane(pedge).set_iedge (pedge.second, iedge); }
|
|
|
|
IVertex disconnect_ivertex (const PVertex& pvertex)
|
|
{
|
|
IVertex out = ivertex (pvertex);
|
|
support_plane(pvertex).set_ivertex (pvertex.second, null_ivertex());
|
|
return out;
|
|
}
|
|
IEdge disconnect_iedge (const PVertex& pvertex)
|
|
{
|
|
IEdge out = iedge (pvertex);
|
|
support_plane(pvertex).set_iedge (pvertex.second, null_iedge());
|
|
return out;
|
|
}
|
|
|
|
struct Queue_element
|
|
{
|
|
PVertex previous;
|
|
PVertex pvertex;
|
|
bool front;
|
|
|
|
Queue_element (const PVertex& previous, const PVertex& pvertex, bool front)
|
|
: previous (previous), pvertex (pvertex), front (front) { }
|
|
};
|
|
|
|
std::vector<PVertex> pvertices_around_ivertex (const PVertex& pvertex, const IVertex& ivertex) const
|
|
{
|
|
std::deque<PVertex> vertices;
|
|
vertices.push_back (pvertex);
|
|
|
|
std::queue<Queue_element> todo;
|
|
PVertex prev, next;
|
|
std::tie (prev, next) = border_prev_and_next (pvertex);
|
|
todo.push (Queue_element (pvertex, prev, true));
|
|
todo.push (Queue_element (pvertex, next, false));
|
|
|
|
while (!todo.empty())
|
|
{
|
|
PVertex previous = todo.front().previous;
|
|
PVertex current = todo.front().pvertex;
|
|
bool front = todo.front().front;
|
|
todo.pop();
|
|
|
|
IEdge iedge = this->iedge (current);
|
|
if (iedge == null_iedge())
|
|
continue;
|
|
|
|
if (source(iedge) != ivertex && target(iedge) != ivertex)
|
|
continue;
|
|
|
|
IVertex other = source(iedge);
|
|
if (other == ivertex)
|
|
other = target(iedge);
|
|
else
|
|
CGAL_assertion (target(iedge) == ivertex);
|
|
|
|
// Filter backwards vertex
|
|
if (direction (current) * Vector_2 (point_2 (current.first, other),
|
|
point_2 (current.first, ivertex))
|
|
< 0)
|
|
continue;
|
|
|
|
if (front)
|
|
vertices.push_front (current);
|
|
else
|
|
vertices.push_back (current);
|
|
|
|
std::tie (prev, next) = border_prev_and_next (current);
|
|
|
|
if (prev == previous)
|
|
{
|
|
CGAL_assertion (next != previous);
|
|
todo.push (Queue_element (current, next, front));
|
|
}
|
|
else
|
|
todo.push (Queue_element (current, prev, front));
|
|
}
|
|
|
|
std::vector<PVertex> out;
|
|
out.reserve (vertices.size());
|
|
std::copy (vertices.begin(), vertices.end(),
|
|
std::back_inserter (out));
|
|
return out;
|
|
}
|
|
|
|
/*******************************
|
|
* Conversions
|
|
*******************************/
|
|
|
|
Point_2 to_2d (KSR::size_t support_plane_idx, const IVertex& ivertex) const
|
|
{ return support_plane(support_plane_idx).to_2d (point_3(ivertex)); }
|
|
Segment_2 to_2d (KSR::size_t support_plane_idx, const Segment_3& segment_3) const
|
|
{ return support_plane(support_plane_idx).to_2d (segment_3); }
|
|
|
|
Point_2 point_2 (const PVertex& pvertex, FT time) const
|
|
{ return support_plane(pvertex).point_2 (pvertex.second, time); }
|
|
Point_2 point_2 (const PVertex& pvertex) const
|
|
{ return point_2 (pvertex, m_current_time); }
|
|
Point_2 point_2 (KSR::size_t support_plane_idx, const IVertex& ivertex) const
|
|
{ return support_plane(support_plane_idx).to_2d(point_3 (ivertex)); }
|
|
|
|
Segment_2 segment_2 (KSR::size_t support_plane_idx, const IEdge& iedge) const
|
|
{ return support_plane(support_plane_idx).to_2d(segment_3(iedge)); }
|
|
|
|
Point_3 to_3d (KSR::size_t support_plane_idx, const Point_2& point_2) const
|
|
{ return support_plane(support_plane_idx).to_3d (point_2); }
|
|
|
|
Point_3 point_3 (const PVertex& pvertex, FT time) const
|
|
{ return support_plane(pvertex).point_3 (pvertex.second, time); }
|
|
Point_3 point_3 (const PVertex& pvertex) const
|
|
{ return point_3 (pvertex, m_current_time); }
|
|
Point_3 point_3 (const IVertex& vertex) const
|
|
{ return m_intersection_graph.point_3 (vertex); }
|
|
|
|
Segment_3 segment_3 (const PEdge& pedge, FT time) const
|
|
{ return support_plane(pedge).segment_3 (pedge.second, time); }
|
|
Segment_3 segment_3 (const PEdge& pedge) const
|
|
{ return segment_3 (pedge, m_current_time); }
|
|
Segment_3 segment_3 (const IEdge& edge) const
|
|
{ return m_intersection_graph.segment_3 (edge); }
|
|
|
|
/*******************************
|
|
* Predicates
|
|
*******************************/
|
|
|
|
std::pair<bool, bool> collision_occured (const PVertex& pvertex, const IEdge& iedge) const
|
|
{
|
|
bool collision = false;
|
|
|
|
for (KSR::size_t support_plane_idx : intersected_planes(iedge))
|
|
{
|
|
if (support_plane_idx < 6)
|
|
return std::make_pair (true, true);
|
|
|
|
for (const PEdge& pedge : pedges(support_plane_idx))
|
|
if (this->iedge(pedge) == iedge)
|
|
{
|
|
Segment_2 iedge_segment = segment_2 (support_plane_idx, iedge);
|
|
|
|
Vector_2 source_2_vertex (iedge_segment.source(), point_2(pvertex));
|
|
|
|
FT prod = iedge_segment.to_vector() * source_2_vertex;
|
|
if (prod < 0)
|
|
continue;
|
|
|
|
if (source_2_vertex.squared_length() <= iedge_segment.squared_length())
|
|
{
|
|
collision = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return std::make_pair (collision, false);
|
|
}
|
|
|
|
/*******************************
|
|
* Operations on polygons
|
|
*******************************/
|
|
|
|
PVertex crop_polygon (const PVertex& pvertex, const IEdge& iedge)
|
|
{
|
|
CGAL_KSR_CERR(3) << "*** Cropping " << str(pvertex) << " along " << str(iedge) << std::endl;
|
|
|
|
Point_2 future_point_a, future_point_b;
|
|
Vector_2 direction_a, direction_b;
|
|
|
|
compute_future_points_and_directions (pvertex, iedge,
|
|
future_point_a, future_point_b,
|
|
direction_a, direction_b);
|
|
|
|
PEdge pedge (pvertex.first, support_plane(pvertex).split_vertex(pvertex.second));
|
|
CGAL_assertion (source(pedge) == pvertex || target(pedge) == pvertex);
|
|
|
|
PVertex other = opposite(pedge, pvertex);
|
|
|
|
CGAL_KSR_CERR(3) << "*** New edge " << str(pedge) << " between " << str(pvertex)
|
|
<< " and " << str(other) << std::endl;
|
|
|
|
connect (pedge, iedge);
|
|
connect (pvertex, iedge);
|
|
connect (other, iedge);
|
|
|
|
support_plane(pvertex).set_point (pvertex.second, future_point_a);
|
|
support_plane(other).set_point (other.second, future_point_b);
|
|
|
|
direction(pvertex) = direction_a;
|
|
direction(other) = direction_b;
|
|
|
|
return other;
|
|
}
|
|
|
|
std::array<PVertex, 3> propagate_polygon (const PVertex& pvertex, const IEdge& iedge)
|
|
{
|
|
CGAL_KSR_CERR(3) << "*** Propagating " << str(pvertex) << " along " << str(iedge) << std::endl;
|
|
|
|
Point_2 original_point = point_2 (pvertex, 0);
|
|
Vector_2 original_direction = direction(pvertex);
|
|
|
|
PVertex other = crop_polygon (pvertex, iedge);
|
|
|
|
PVertex propagated = add_pvertex (pvertex.first, original_point);
|
|
direction(propagated) = original_direction;
|
|
|
|
std::array<PVertex, 3> pvertices;
|
|
|
|
pvertices[0] = pvertex;
|
|
pvertices[1] = other;
|
|
pvertices[2] = propagated;
|
|
|
|
PFace pface = add_pface (pvertices);
|
|
CGAL_assertion (pface.second != Face_index());
|
|
|
|
CGAL_KSR_CERR(3) << "*** New face " << lstr(pface) << std::endl;
|
|
|
|
return pvertices;
|
|
}
|
|
|
|
void transfer_vertex (const PVertex& pvertex, const PVertex& pother)
|
|
{
|
|
CGAL_KSR_CERR(3) << "*** Transfering " << str(pother) << " through " << str(pvertex) << std::endl;
|
|
|
|
// If pvertex is adjacent to one or two
|
|
PFace source_face, target_face;
|
|
std::tie (source_face, target_face) = pfaces_of_pvertex (pvertex);
|
|
|
|
CGAL_KSR_CERR(3) << "*** Initial faces: " << lstr(source_face)
|
|
<< " and " << lstr(target_face) << std::endl;
|
|
|
|
PFace common_pface = pface_of_pvertex (pother);
|
|
|
|
if (common_pface == target_face)
|
|
std::swap (source_face, target_face);
|
|
CGAL_assertion (common_pface == source_face);
|
|
|
|
if (target_face == null_pface())
|
|
{
|
|
CGAL_assertion_msg (false, "TODO: create target face");
|
|
}
|
|
else
|
|
{
|
|
PVertex pthird = next(pother);
|
|
if (pthird == pvertex)
|
|
pthird = prev(pother);
|
|
|
|
IEdge iedge = disconnect_iedge (pvertex);
|
|
|
|
PEdge pedge = null_pedge();
|
|
for (PEdge pe : pedges_around_pvertex (pvertex))
|
|
if (this->iedge(pe) == iedge)
|
|
{
|
|
pedge = pe;
|
|
break;
|
|
}
|
|
CGAL_assertion (pedge != null_pedge());
|
|
|
|
Halfedge_index hi = mesh(pedge).halfedge(pedge.second);
|
|
if (mesh(pedge).face(hi) != common_pface.second)
|
|
hi = mesh(pedge).opposite(hi);
|
|
CGAL_assertion (mesh(pedge).face(hi) == common_pface.second);
|
|
|
|
if (mesh(pedge).target(hi) == pvertex.second)
|
|
{
|
|
CGAL::Euler::shift_target (hi, mesh(pedge));
|
|
}
|
|
else
|
|
{
|
|
CGAL_assertion (mesh(pedge).source(hi) == pvertex.second);
|
|
CGAL::Euler::shift_source (hi, mesh(pedge));
|
|
}
|
|
|
|
Vector_2 new_direction;
|
|
|
|
Line_2 iedge_line = segment_2(pother.first, iedge).supporting_line();
|
|
Point_2 pinit = iedge_line.projection(point_2 (pother, m_current_time));
|
|
|
|
direction(pvertex) = direction(pother);
|
|
support_plane(pother).set_point (pvertex.second,
|
|
pinit - direction(pvertex) * m_current_time);
|
|
|
|
Line_2 future_line (point_2 (pvertex, m_current_time + 1),
|
|
point_2 (pthird, m_current_time + 1));
|
|
|
|
Point_2 future_point = KSR::intersection_2<Point_2> (future_line, iedge_line);
|
|
|
|
direction(pother) = Vector_2 (pinit, future_point);
|
|
support_plane(pother).set_point (pother.second,
|
|
pinit - direction(pother) * m_current_time);
|
|
|
|
connect (pother, iedge);
|
|
}
|
|
|
|
CGAL_KSR_CERR(3) << "*** New faces: " << lstr(source_face)
|
|
<< " and " << lstr(target_face) << std::endl;
|
|
|
|
}
|
|
|
|
void merge_pvertices (const PVertex& pvertex, const PVertex& pother)
|
|
{
|
|
CGAL_KSR_CERR(3) << "*** Merging " << str(pvertex) << " with " << str(pother) << std::endl;
|
|
|
|
Halfedge_index hi = mesh(pvertex).halfedge(pother.second, pvertex.second);
|
|
disconnect_ivertex (pother);
|
|
CGAL::Euler::join_vertex(hi, mesh(pvertex));
|
|
}
|
|
|
|
std::vector<PVertex> merge_pvertices_on_ivertex (std::vector<PVertex>& pvertices,
|
|
const IVertex& ivertex)
|
|
{
|
|
KSR::size_t support_plane_idx = pvertices.front().first;
|
|
|
|
// Get prev and next along border
|
|
PVertex prev, next, ignored;
|
|
std::tie (prev, ignored) = border_prev_and_next (pvertices.front());
|
|
if (prev == pvertices[1])
|
|
std::swap (prev, ignored);
|
|
|
|
std::tie (next, ignored) = border_prev_and_next (pvertices.back());
|
|
if (next == pvertices[pvertices.size() - 2])
|
|
std::swap (next, ignored);
|
|
|
|
// Copy front/back to remember position/direction
|
|
PVertex front (support_plane_idx, support_plane(support_plane_idx).duplicate_vertex(pvertices.front().second));
|
|
PVertex back (support_plane_idx,support_plane(support_plane_idx).duplicate_vertex(pvertices.back().second));
|
|
|
|
if (CGAL::orientation (point_2 (prev), point_2 (support_plane_idx, ivertex), point_2 (next)) == CGAL::LEFT_TURN)
|
|
{
|
|
std::swap (prev, next);
|
|
std::swap (front, back);
|
|
}
|
|
|
|
// Freeze vertices
|
|
for (PVertex& pvertex : pvertices)
|
|
{
|
|
Point_2 p = point_2 (support_plane_idx, ivertex);
|
|
support_plane(pvertex).direction (pvertex.second) = CGAL::NULL_VECTOR;
|
|
support_plane(pvertex).set_point (pvertex.second, p);
|
|
}
|
|
|
|
PVertex pvertex = pvertices.front();
|
|
connect (pvertex, ivertex);
|
|
|
|
|
|
// Join vertices
|
|
for (std::size_t i = 1; i < pvertices.size(); ++ i)
|
|
{
|
|
Halfedge_index hi = mesh(support_plane_idx).halfedge(pvertices[i].second, pvertex.second);
|
|
disconnect_ivertex (pvertices[i]);
|
|
CGAL::Euler::join_vertex(hi, mesh(support_plane_idx));
|
|
}
|
|
|
|
Incident_iedges i_iedges = incident_iedges (ivertex);
|
|
std::vector<std::pair<IEdge, Direction_2> > iedges;
|
|
std::copy (i_iedges.begin(), i_iedges.end(),
|
|
boost::make_function_output_iterator
|
|
([&](const IEdge& ie) -> void
|
|
{
|
|
if (intersected_planes(ie).find (support_plane_idx)
|
|
== intersected_planes(ie).end())
|
|
return;
|
|
|
|
Direction_2 dir (point_2 (support_plane_idx, opposite (ie, ivertex))
|
|
- point_2 (support_plane_idx, ivertex));
|
|
iedges.push_back (std::make_pair (ie, dir));
|
|
}));
|
|
|
|
std::sort (iedges.begin(), iedges.end(),
|
|
[&](const std::pair<IEdge, Direction_2>& a,
|
|
const std::pair<IEdge, Direction_2>& b) -> bool
|
|
{
|
|
return a.second < b.second;
|
|
});
|
|
|
|
bool back_constrained = false;
|
|
if (iedge(next) != null_iedge()
|
|
&& (source(iedge(next)) == ivertex || target(iedge(next)) == ivertex))
|
|
back_constrained = true;
|
|
|
|
bool front_constrained = false;
|
|
if (iedge(prev) != null_iedge()
|
|
&& (source(iedge(prev)) == ivertex || target(iedge(prev)) == ivertex))
|
|
front_constrained = true;
|
|
|
|
std::cerr << "Prev = " << point_2 (prev) << " / " << direction (prev) << std::endl
|
|
<< "Front = " << point_2 (front) << " / " << direction (front) << std::endl
|
|
<< "Back = " << point_2 (back) << " / " << direction (back) << std::endl
|
|
<< "Next = " << point_2 (next) << " / " << direction (next) << std::endl;
|
|
|
|
std::vector<PVertex> new_vertices;
|
|
|
|
if (back_constrained && front_constrained) // Closing case
|
|
{
|
|
CGAL_assertion_msg (false, "TODO: closing");
|
|
}
|
|
else if (back_constrained) // Border case
|
|
{
|
|
std::cerr << "Back border case" << std::endl;
|
|
KSR::size_t other_side_limit = line_idx(next);
|
|
|
|
Direction_2 dir (point_2(prev) - point_2 (pvertex));
|
|
|
|
std::reverse (iedges.begin(), iedges.end());
|
|
|
|
KSR::size_t first_idx = KSR::no_element();
|
|
for (std::size_t i = 0; i < iedges.size(); ++ i)
|
|
{
|
|
if (dir.counterclockwise_in_between(iedges[(i+1)%iedges.size()].second,
|
|
iedges[i].second))
|
|
{
|
|
first_idx = (i+1)%iedges.size();
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::ofstream ("first.polylines.txt")
|
|
<< "2 " << segment_3 (iedges[first_idx].first) << std::endl;
|
|
|
|
CGAL_assertion (first_idx != KSR::no_element());
|
|
|
|
std::vector<IEdge> crossed;
|
|
|
|
KSR::size_t iedge_idx = first_idx;
|
|
while (true)
|
|
{
|
|
const IEdge& iedge = iedges[iedge_idx].first;
|
|
|
|
bool collision, bbox_reached;
|
|
std::tie (collision, bbox_reached) = collision_occured (pvertex, iedge);
|
|
bool limit_reached = (line_idx(iedge) == other_side_limit);
|
|
|
|
crossed.push_back (iedge);
|
|
|
|
std::ofstream ("next.polylines.txt")
|
|
<< "2 " << segment_3 (iedge) << std::endl;
|
|
if (limit_reached || bbox_reached)
|
|
break;
|
|
|
|
iedge_idx = (iedge_idx + 1) % iedges.size();
|
|
}
|
|
|
|
std::cerr << "IEdges crossed = " << crossed.size() << std::endl;
|
|
|
|
std::vector<Point_2> future_points (crossed.size());
|
|
std::vector<Vector_2> future_directions (crossed.size());
|
|
for (std::size_t i = 0; i < crossed.size(); ++ i)
|
|
compute_future_point_and_direction (back, prev, crossed[i], future_points[i], future_directions[i]);
|
|
|
|
PVertex previous = null_pvertex();
|
|
|
|
for (std::size_t i = 0; i < crossed.size(); ++ i)
|
|
{
|
|
if (i == 0) // crop
|
|
{
|
|
PVertex cropped (support_plane_idx, support_plane(pvertex).split_edge (pvertex.second, prev.second));
|
|
|
|
PEdge pedge (support_plane_idx, support_plane(pvertex).edge (pvertex.second, cropped.second));
|
|
|
|
new_vertices.push_back (cropped);
|
|
|
|
connect (pedge, crossed[i]);
|
|
connect (cropped, crossed[i]);
|
|
|
|
support_plane(cropped).set_point (cropped.second, future_points[i]);
|
|
direction(cropped) = future_directions[i];
|
|
previous = cropped;
|
|
std::cerr << point_2 (cropped) << " -> " << direction(cropped) << std::endl;
|
|
}
|
|
else // create triangle face
|
|
{
|
|
PVertex propagated = add_pvertex (pvertex.first, future_points[i]);
|
|
direction(propagated) = future_directions[i];
|
|
new_vertices.push_back (propagated);
|
|
|
|
add_pface (std::array<PVertex, 3>{ pvertex, previous, propagated });
|
|
previous = propagated;
|
|
}
|
|
}
|
|
}
|
|
else if (front_constrained) // Border case
|
|
{
|
|
std::cerr << "Front border case" << std::endl;
|
|
|
|
KSR::size_t other_side_limit = line_idx(prev);
|
|
|
|
Direction_2 dir (point_2(next) - point_2 (pvertex));
|
|
|
|
KSR::size_t first_idx = KSR::no_element();
|
|
for (std::size_t i = 0; i < iedges.size(); ++ i)
|
|
{
|
|
if (dir.counterclockwise_in_between(iedges[i].second,
|
|
iedges[(i+1)%iedges.size()].second))
|
|
|
|
{
|
|
first_idx = (i+1)%iedges.size();
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::ofstream ("first.polylines.txt")
|
|
<< "2 " << segment_3 (iedges[first_idx].first) << std::endl;
|
|
|
|
CGAL_assertion (first_idx != KSR::no_element());
|
|
|
|
std::vector<IEdge> crossed;
|
|
|
|
KSR::size_t iedge_idx = first_idx;
|
|
while (true)
|
|
{
|
|
const IEdge& iedge = iedges[iedge_idx].first;
|
|
|
|
bool collision, bbox_reached;
|
|
std::tie (collision, bbox_reached) = collision_occured (pvertex, iedge);
|
|
bool limit_reached = (line_idx(iedge) == other_side_limit);
|
|
|
|
std::ofstream ("next.polylines.txt")
|
|
<< "2 " << segment_3 (iedge) << std::endl;
|
|
crossed.push_back (iedge);
|
|
|
|
if (limit_reached || bbox_reached)
|
|
break;
|
|
|
|
iedge_idx = (iedge_idx + 1) % iedges.size();
|
|
}
|
|
|
|
std::cerr << "IEdges crossed = " << crossed.size() << std::endl;
|
|
|
|
std::vector<Point_2> future_points (crossed.size());
|
|
std::vector<Vector_2> future_directions (crossed.size());
|
|
for (std::size_t i = 0; i < crossed.size(); ++ i)
|
|
compute_future_point_and_direction (front, next, crossed[i], future_points[i], future_directions[i]);
|
|
|
|
PVertex previous = null_pvertex();
|
|
|
|
for (std::size_t i = 0; i < crossed.size(); ++ i)
|
|
{
|
|
if (i == 0) // crop
|
|
{
|
|
PVertex cropped (support_plane_idx, support_plane(pvertex).split_edge (pvertex.second, next.second));
|
|
|
|
PEdge pedge (support_plane_idx, support_plane(pvertex).edge (pvertex.second, cropped.second));
|
|
|
|
CGAL_assertion (cropped != pvertex);
|
|
|
|
new_vertices.push_back (cropped);
|
|
|
|
connect (pedge, crossed[i]);
|
|
connect (cropped, crossed[i]);
|
|
|
|
support_plane(cropped).set_point (cropped.second, future_points[i]);
|
|
direction(cropped) = future_directions[i];
|
|
previous = cropped;
|
|
std::cerr << point_2 (cropped) << " -> " << direction(cropped) << std::endl;
|
|
}
|
|
else // create triangle face
|
|
{
|
|
PVertex propagated = add_pvertex (pvertex.first, future_points[i]);
|
|
direction(propagated) = future_directions[i];
|
|
new_vertices.push_back (propagated);
|
|
|
|
add_pface (std::array<PVertex, 3>{ pvertex, previous, propagated });
|
|
previous = propagated;
|
|
}
|
|
}
|
|
}
|
|
else // Open case
|
|
{
|
|
std::cerr << "Open case" << std::endl;
|
|
|
|
auto pvertex_to_point =
|
|
[&](const PVertex& a) -> Point_2
|
|
{
|
|
return point_2(a);
|
|
};
|
|
// If open case, prev/pvertex/next are collinear, so the
|
|
// orientation is not reliable.
|
|
PFace fprev = pface_of_pvertex(prev);
|
|
Point_2 pprev = CGAL::centroid
|
|
(boost::make_transform_iterator (pvertices_of_pface(fprev).begin(), pvertex_to_point),
|
|
boost::make_transform_iterator (pvertices_of_pface(fprev).end(), pvertex_to_point));
|
|
PFace fnext = pface_of_pvertex(next);
|
|
Point_2 pnext = CGAL::centroid
|
|
(boost::make_transform_iterator (pvertices_of_pface(fnext).begin(), pvertex_to_point),
|
|
boost::make_transform_iterator (pvertices_of_pface(fnext).end(), pvertex_to_point));
|
|
|
|
if (CGAL::orientation (pprev, point_2 (support_plane_idx, ivertex), pnext) == CGAL::LEFT_TURN)
|
|
{
|
|
std::swap (prev, next);
|
|
std::swap (front, back);
|
|
}
|
|
|
|
Direction_2 dir_next (point_2(next) - point_2 (pvertex));
|
|
Direction_2 dir_prev (point_2(prev) - point_2 (pvertex));
|
|
KSR::size_t first_idx = KSR::no_element();
|
|
for (std::size_t i = 0; i < iedges.size(); ++ i)
|
|
{
|
|
if (dir_next.counterclockwise_in_between(iedges[i].second,
|
|
iedges[(i+1)%iedges.size()].second))
|
|
|
|
{
|
|
first_idx = (i+1)%iedges.size();
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::vector<IEdge> crossed;
|
|
|
|
KSR::size_t iedge_idx = first_idx;
|
|
while (true)
|
|
{
|
|
const IEdge& iedge = iedges[iedge_idx].first;
|
|
const Direction_2& dir = iedges[iedge_idx].second;
|
|
|
|
if (!dir.counterclockwise_in_between (dir_next, dir_prev))
|
|
break;
|
|
|
|
crossed.push_back (iedge);
|
|
|
|
iedge_idx = (iedge_idx + 1) % iedges.size();
|
|
}
|
|
|
|
std::cerr << "IEdges crossed = " << crossed.size() << std::endl;
|
|
|
|
std::vector<Point_2> future_points (crossed.size());
|
|
std::vector<Vector_2> future_directions (crossed.size());
|
|
for (std::size_t i = 0; i < crossed.size(); ++ i)
|
|
compute_future_point_and_direction (pvertex, prev, next, crossed[i], future_points[i], future_directions[i]);
|
|
|
|
{
|
|
PVertex cropped (support_plane_idx, support_plane(pvertex).split_edge (pvertex.second, next.second));
|
|
|
|
PEdge pedge (support_plane_idx, support_plane(pvertex).edge (pvertex.second, cropped.second));
|
|
|
|
new_vertices.push_back (cropped);
|
|
|
|
connect (pedge, crossed.front());
|
|
connect (cropped, crossed.front());
|
|
|
|
support_plane(cropped).set_point (cropped.second, future_points.front());
|
|
direction(cropped) = future_directions.front();
|
|
}
|
|
|
|
for (std::size_t i = 1; i < crossed.size() - 1; ++ i)
|
|
{
|
|
PVertex propagated = add_pvertex (pvertex.first, future_points[i]);
|
|
direction(propagated) = future_directions[i];
|
|
new_vertices.push_back (propagated);
|
|
}
|
|
|
|
{
|
|
PVertex cropped (support_plane_idx, support_plane(pvertex).split_edge (pvertex.second, prev.second));
|
|
|
|
PEdge pedge (support_plane_idx, support_plane(pvertex).edge (pvertex.second, cropped.second));
|
|
|
|
new_vertices.push_back (cropped);
|
|
|
|
connect (pedge, crossed.back());
|
|
connect (cropped, crossed.back());
|
|
|
|
support_plane(cropped).set_point (cropped.second, future_points.back());
|
|
direction(cropped) = future_directions.back();
|
|
}
|
|
std::cerr << new_vertices.size() << " new vertice(s)" << std::endl;
|
|
for (std::size_t i = 0; i < new_vertices.size() - 1; ++ i)
|
|
add_pface (std::array<PVertex, 3>{ new_vertices[i], new_vertices[i+1], pvertex });
|
|
}
|
|
|
|
support_plane(support_plane_idx).remove_vertex(front.second);
|
|
support_plane(support_plane_idx).remove_vertex(back.second);
|
|
|
|
new_vertices.push_back (pvertex); // We push it just so that its
|
|
// IVertex is deactivated before computing new events
|
|
return new_vertices;
|
|
}
|
|
|
|
|
|
void update_positions (FT time)
|
|
{
|
|
m_current_time = time;
|
|
}
|
|
|
|
inline std::string str (const PVertex& pvertex) const
|
|
{ return "PVertex(" + std::to_string(pvertex.first) + ":v" + std::to_string(pvertex.second) + ")"; }
|
|
inline std::string str (const PEdge& pedge) const
|
|
{ return "PEdge(" + std::to_string(pedge.first) + ":e" + std::to_string(pedge.second) + ")"; }
|
|
inline std::string str (const PFace& pface) const
|
|
{ return "PFace(" + std::to_string(pface.first) + ":f" + std::to_string(pface.second) + ")"; }
|
|
inline std::string str (const IVertex& ivertex) const
|
|
{ return "IVertex(" + std::to_string(ivertex) + ")"; }
|
|
inline std::string str (const IEdge& iedge) const
|
|
{ std::ostringstream oss; oss << "IEdge" << iedge; return oss.str(); }
|
|
|
|
inline std::string lstr (const PFace& pface) const
|
|
{
|
|
std::string out = "PFace(" + std::to_string(pface.first) + ":f" + std::to_string(pface.second) + ")[";
|
|
for (PVertex pvertex : pvertices_of_pface (pface))
|
|
out += "v" + std::to_string(pvertex.second);
|
|
out += "]";
|
|
return out;
|
|
}
|
|
private:
|
|
|
|
template <typename PSimplex>
|
|
const Support_plane& support_plane (const PSimplex& psimplex) const { return support_plane(psimplex.first); }
|
|
const Support_plane& support_plane (KSR::size_t idx) const { return m_support_planes[idx]; }
|
|
template <typename PSimplex>
|
|
Support_plane& support_plane (const PSimplex& psimplex) { return support_plane(psimplex.first); }
|
|
Support_plane& support_plane (KSR::size_t idx) { return m_support_planes[idx]; }
|
|
|
|
template <typename PSimplex>
|
|
const Mesh& mesh (const PSimplex& psimplex) const { return mesh(psimplex.first); }
|
|
const Mesh& mesh (KSR::size_t support_plane_idx) const { return support_plane(support_plane_idx).mesh(); }
|
|
template <typename PSimplex>
|
|
Mesh& mesh (const PSimplex& psimplex) { return mesh(psimplex.first); }
|
|
Mesh& mesh (KSR::size_t support_plane_idx) { return support_plane(support_plane_idx).mesh(); }
|
|
|
|
void compute_future_points_and_directions (const PVertex& pvertex, const IEdge& iedge,
|
|
Point_2& future_point_a, Point_2& future_point_b,
|
|
Vector_2& direction_a, Vector_2& direction_b) const
|
|
{
|
|
PVertex prev (pvertex.first, support_plane(pvertex).prev(pvertex.second));
|
|
PVertex next (pvertex.first, support_plane(pvertex).next(pvertex.second));
|
|
|
|
Line_2 iedge_line = segment_2(pvertex.first, iedge).supporting_line();
|
|
Point_2 pinit = iedge_line.projection(point_2 (pvertex, m_current_time));
|
|
|
|
Line_2 future_line_prev (point_2 (prev, m_current_time + 1),
|
|
point_2 (pvertex, m_current_time + 1));
|
|
Line_2 future_line_next (point_2 (next, m_current_time + 1),
|
|
point_2 (pvertex, m_current_time + 1));
|
|
|
|
future_point_a = KSR::intersection_2<Point_2> (future_line_prev, iedge_line);
|
|
future_point_b = KSR::intersection_2<Point_2> (future_line_next, iedge_line);
|
|
direction_a = Vector_2 (pinit, future_point_a);
|
|
direction_b = Vector_2 (pinit, future_point_b);
|
|
future_point_a = pinit - m_current_time * direction_a;
|
|
future_point_b = pinit - m_current_time * direction_b;
|
|
}
|
|
|
|
void compute_future_point_and_direction (const PVertex& pvertex, const PVertex& next,
|
|
const IEdge& iedge,
|
|
Point_2& future_point, Vector_2& direction) const
|
|
{
|
|
if (this->iedge(pvertex) != null_iedge()
|
|
&& line_idx(pvertex) == line_idx(iedge))
|
|
{
|
|
std::cerr << "Found limit" << std::endl;
|
|
future_point = point_2 (pvertex, 0);
|
|
direction = this->direction (pvertex);
|
|
return;
|
|
}
|
|
Line_2 iedge_line = segment_2(pvertex.first, iedge).supporting_line();
|
|
Point_2 pinit = iedge_line.projection(point_2 (pvertex, m_current_time));
|
|
|
|
Line_2 future_line_next (point_2 (next, m_current_time + 1),
|
|
point_2 (pvertex, m_current_time + 1));
|
|
|
|
future_point = KSR::intersection_2<Point_2> (future_line_next, iedge_line);
|
|
direction = Vector_2 (pinit, future_point);
|
|
future_point = pinit - m_current_time * direction;
|
|
}
|
|
|
|
void compute_future_point_and_direction (const PVertex& pvertex,
|
|
const PVertex& prev, const PVertex& next,
|
|
const IEdge& iedge,
|
|
Point_2& future_point, Vector_2& direction) const
|
|
{
|
|
Line_2 iedge_line = segment_2(pvertex.first, iedge).supporting_line();
|
|
Point_2 pinit = iedge_line.projection(point_2 (pvertex, m_current_time));
|
|
|
|
Line_2 future_line (point_2 (next, m_current_time + 1),
|
|
point_2 (prev, m_current_time + 1));
|
|
|
|
future_point = KSR::intersection_2<Point_2> (future_line, iedge_line);
|
|
direction = Vector_2 (pinit, future_point);
|
|
future_point = pinit - m_current_time * direction;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}} // namespace CGAL::KSR_3
|
|
|
|
|
|
#endif // CGAL_KSR_3_DATA_STRUCTURE_H
|