added/fixed assertions, fixed bug with identical planes when extracting volumes, fixed bug for partially connected pvertices in polygon splitter

This commit is contained in:
Dmitry Anisimov 2020-12-15 13:30:11 +01:00
parent e5cf7ade94
commit c77fa218f4
8 changed files with 207 additions and 64 deletions

View File

@ -0,0 +1,12 @@
OFF
8 2 0
0.0 0.0 0.0
1.0 0.0 0.0
1.0 1.0 0.0
0.0 1.0 0.0
0.5 0.5 0.0
0.5 1.5 0.0
0.5 1.5 1.0
0.5 0.5 1.0
4 0 1 2 3
4 4 5 6 7

View File

@ -155,8 +155,9 @@ template<typename Vector_d>
inline const Vector_d normalize(const Vector_d& v) {
using Traits = typename Kernel_traits<Vector_d>::Kernel;
using FT = typename Traits::FT;
const FT dot_prod = CGAL::abs(v * v);
return v / static_cast<FT>(CGAL::sqrt(CGAL::to_double(dot_prod)));
const FT dot_product = CGAL::abs(v * v);
CGAL_assertion(dot_product != FT(0));
return v / static_cast<FT>(CGAL::sqrt(CGAL::to_double(dot_product)));
}
template<typename Type1, typename Type2, typename ResultType>

View File

@ -3437,6 +3437,7 @@ public:
const Segment_3 segment = segment_3(pedge);
const Line_3 line(segment.source(), segment.target());
Point_3 midp = CGAL::midpoint(segment.source(), segment.target());
// std::cout << "midp: " << midp << std::endl;
Vector_3 norm(segment.source(), segment.target());
norm = KSR::normalize(norm);
const Plane_3 plane(midp, norm);
@ -3465,6 +3466,8 @@ public:
const FT cz = volume_centroid.z();
FT d = (norm.x() * cx + norm.y() * cy + norm.z() * cz + plane.d());
// std::cout << "1 d: " << d << std::endl;
// std::cout << "1 norm: " << norm << std::endl;
const Plane_3 tr_plane(midp + norm * d, norm);
Point_3 inter;
const bool is_intersection_found = KSR::intersection(line, tr_plane, inter);
@ -3472,11 +3475,19 @@ public:
std::cout << "d = " << d << std::endl;
}
CGAL_assertion(is_intersection_found);
// std::cout << "inter: " << inter << std::endl;
d = KSR::distance(midp, inter);
norm = Vector_3(midp, inter);
norm = KSR::normalize(norm);
for (auto& point : points) {
point += norm * d;
// std::cout << "2 d: " << d << std::endl;
// std::cout << "2 norm: " << norm << std::endl;
if (d != FT(0)) {
CGAL_assertion(norm != Vector_3(FT(0), FT(0), FT(0)));
norm = KSR::normalize(norm);
for (auto& point : points) {
point += norm * d;
}
}
if (is_debug) {

View File

@ -88,7 +88,7 @@ public:
bounding_box_to_polygons(bbox, bbox_faces);
add_polygons(input_range, polygon_map, bbox_faces);
if (m_verbose) std::cout << "* intersecting input polygons ...";
if (m_verbose) std::cout << "* intersecting input polygons ... ";
if (m_debug) {
KSR_3::dump(m_data, "init");
// KSR_3::dump_segmented_edges(m_data, "init");
@ -99,9 +99,9 @@ public:
m_data.check_integrity();
set_k_intersections(k);
if (m_verbose) std::cout << " done" << std::endl;
if (m_verbose) std::cout << "done" << std::endl;
if (m_debug) {
KSR_3::dump(m_data, "intersected");
KSR_3::dump(m_data, "intersected-iter-1000");
// KSR_3::dump_segmented_edges(m_data, "intersected");
}
@ -393,6 +393,9 @@ private:
for (KSR::size_t i = 0; i < m_data.number_of_support_planes(); ++i) {
Polygon_splitter splitter(m_data);
splitter.split_support_plane(i);
if (i >= 6 && m_debug) {
KSR_3::dump(m_data, "intersected-iter-" + std::to_string(i));
}
}
}

View File

@ -123,7 +123,7 @@ public:
CGAL_assertion(m_graph[edge].line >= 0);
ig.graph()[ed].line = m_graph[edge].line;
CGAL_assertion(m_graph[edge].planes.size() >= 2);
CGAL_assertion(m_graph[edge].planes.size() >= 1);
ig.graph()[ed].planes = m_graph[edge].planes;
CGAL_assertion(m_graph[edge].active);

View File

@ -51,6 +51,7 @@ private:
using Line_2 = typename Kernel::Line_2;
using Vector_2 = typename Kernel::Vector_2;
using Triangle_2 = typename Kernel::Triangle_2;
using Segment_2 = typename Kernel::Segment_2;
using PVertex = typename Data_structure::PVertex;
using PFace = typename Data_structure::PFace;
@ -106,21 +107,15 @@ public:
void split_support_plane(const KSR::size_t support_plane_idx) {
std::cout.precision(20);
std::cout << "current sp index: " << support_plane_idx << std::endl;
// Create cdt.
std::cout.precision(20);
std::vector<KSR::size_t> original_input;
std::vector< std::vector<Point_2> > original_faces;
initialize_cdt(support_plane_idx, original_input, original_faces);
CGAL_assertion(original_faces.size() >= 1);
CGAL_assertion(original_input.size() == original_faces.size());
tag_cdt_exterior_faces();
tag_cdt_interior_faces();
if (support_plane_idx >= 6) {
dump(true, 0, support_plane_idx, "original-faces.ply");
// dump(true, 1, support_plane_idx, "original-input.ply");
} else {
CGAL_assertion(original_faces.size() == 1);
}
// Split polygons using cdt.
m_data.clear_polygon_faces(support_plane_idx);
@ -438,8 +433,10 @@ private:
void set_new_adjacencies(
const KSR::size_t support_plane_idx) {
// std::cout << std::endl << "support plane idx: " << support_plane_idx << std::endl;
const auto all_pvertices = m_data.pvertices(support_plane_idx);
for (const auto pvertex : all_pvertices) {
// std::cout << "pvertex: " << m_data.point_3(pvertex) << std::endl;
bool is_frozen = false;
auto iedge = Data_structure::null_iedge();
@ -449,11 +446,15 @@ private:
// Search for a frozen pvertex.
const auto pedges = m_data.pedges_around_pvertex(pvertex);
for (const auto pedge : pedges) {
// std::cout << "pedge: 2 " << m_data.segment_3(pedge) << " : "
// << m_data.has_iedge(pedge) << std::endl;
if (m_data.has_iedge(pedge)) {
if (iedge == Data_structure::null_iedge()) {
// std::cout << "empty iedge" << std::endl;
iedge = m_data.iedge(pedge);
} else {
// std::cout << "frozen pvertex" << std::endl;
is_frozen = true;
break;
}
@ -461,9 +462,12 @@ private:
const auto opposite = m_data.opposite(pedge, pvertex);
if (neighbors.first == Data_structure::null_pvertex()) {
neighbors.first = opposite;
// std::cout << "assigned first neighbor: " << m_data.point_3(opposite) << std::endl;
} else {
CGAL_assertion(neighbors.first != Data_structure::null_pvertex());
CGAL_assertion(neighbors.second == Data_structure::null_pvertex());
neighbors.second = opposite;
// std::cout << "assigned second neighbor: " << m_data.point_3(opposite) << std::endl;
}
}
}
@ -479,55 +483,66 @@ private:
continue;
}
m_data.connect(pvertex, iedge);
CGAL_assertion(
neighbors.first != Data_structure::null_pvertex() &&
neighbors.second != Data_structure::null_pvertex());
// CGAL_assertion(
// neighbors.first != Data_structure::null_pvertex() &&
// neighbors.second != Data_structure::null_pvertex());
// Set future direction.
bool first_okay = (m_input.find(neighbors.first) != m_input.end());
auto last = pvertex;
auto curr = neighbors.first;
while (!first_okay) {
PVertex next, ignored;
std::tie(next, ignored) = m_data.border_prev_and_next(curr);
if (next == last) {
std::swap(next, ignored);
}
CGAL_assertion(ignored == last);
last = curr; curr = next;
if (m_input.find(curr) != m_input.end()) {
neighbors.first = curr;
first_okay = true;
}
bool is_first_okay = false;
if (neighbors.first != Data_structure::null_pvertex()) {
is_first_okay = update_neighbor(pvertex, neighbors.first);
}
bool second_okay = (m_input.find(neighbors.second) != m_input.end());
last = pvertex;
curr = neighbors.second;
while (!second_okay) {
PVertex next, ignored;
std::tie(next, ignored) = m_data.border_prev_and_next(curr);
if (next == last) {
std::swap(next, ignored);
}
CGAL_assertion(ignored == last);
last = curr; curr = next;
if (m_input.find(curr) != m_input.end()) {
neighbors.second = curr;
second_okay = true;
}
bool is_second_okay = false;
if (neighbors.second != Data_structure::null_pvertex()) {
is_second_okay = update_neighbor(pvertex, neighbors.second);
}
const Line_2 future_line(
m_data.point_2(neighbors.first, FT(1)), m_data.point_2(neighbors.second, FT(1)));
Line_2 future_line;
if (is_first_okay && is_second_okay) {
future_line = Line_2(
m_data.point_2(neighbors.first , FT(1)),
m_data.point_2(neighbors.second, FT(1)));
} else {
CGAL_assertion(is_first_okay && !is_second_okay);
future_line = Line_2(
m_data.point_2(pvertex , FT(1)),
m_data.point_2(neighbors.first, FT(1)));
}
CGAL_assertion(future_line != Line_2());
const auto intersection_line = m_data.segment_2(support_plane_idx, iedge).supporting_line();
const Point_2 inter = KSR::intersection<Point_2>(intersection_line, future_line);
m_data.direction(pvertex) = Vector_2(m_data.point_2(pvertex, FT(0)), inter);
const Point_2 future_point = KSR::intersection<Point_2>(intersection_line, future_line);
const auto pinit = m_data.point_2(pvertex, FT(0));
const Vector_2 future_direction(pinit, future_point);
m_data.direction(pvertex) = future_direction;
// std::cout << "future point: " << m_data.to_3d(pvertex.first, future_point) << std::endl;
}
}
const bool update_neighbor(
const PVertex& pvertex, PVertex& neighbor) const {
bool is_okay = (m_input.find(neighbor) != m_input.end());
auto last = pvertex;
auto curr = neighbor;
while (!is_okay) {
PVertex next, ignored;
std::tie(next, ignored) = m_data.border_prev_and_next(curr);
if (next == last) {
std::swap(next, ignored);
}
CGAL_assertion(ignored == last);
last = curr; curr = next;
if (m_input.find(curr) != m_input.end()) {
neighbor = curr;
is_okay = true;
}
}
return is_okay;
}
void locate_pface_among_coplanar_pfaces(
const PFace& pface) {
@ -550,6 +565,15 @@ private:
std::vector<Point_2> points;
std::vector<Weighted_point> wps;
const bool is_debug = false;
if (is_debug) {
std::cout << std::endl << "support plane idx: " << support_plane_idx << std::endl;
std::cout << "dumping support plane ... ";
dump(true, 0, support_plane_idx, "support-plane-" +
std::to_string(support_plane_idx) + ".ply");
std::cout << "done" << std::endl;
}
// Find bbox of the support plane.
const auto& iedges = m_data.iedges(support_plane_idx);
points.reserve(iedges.size() * 2);
@ -591,17 +615,105 @@ private:
using Vertex_handle = typename Regular_triangulation::Vertex_handle;
std::vector<Vertex_handle> vhs;
vhs.reserve(original_faces.size());
for (const auto& wp : wps) {
const auto vh = triangulation.insert(wp);
vhs.push_back(vh);
for (std::size_t i = 0; i < wps.size(); ++i) {
const auto& wp = wps[i];
if (i < 4) triangulation.insert(wp);
else {
const auto vh = triangulation.insert(wp);
vhs.push_back(vh);
}
}
CGAL_assertion(triangulation.is_valid());
dump_power_diagram(triangulation, support_plane_idx);
if (is_debug) {
std::cout << "dumping power cdt/diagram ... ";
dump_power_cdt_and_diagram(triangulation, support_plane_idx);
std::cout << "done" << std::endl;
}
// Filter all necessary bisectors.
if (is_debug) {
std::cout << "vhs 0: " << m_data.to_3d(support_plane_idx, vhs[0]->point().point()) << std::endl;
std::cout << "vhs 1: " << m_data.to_3d(support_plane_idx, vhs[1]->point().point()) << std::endl;
}
CGAL_assertion_msg(false,
"TODO: POLYGON SPLITTER, ADD BISECTORS!");
auto curr = triangulation.incident_edges(vhs[0]);
const auto end = curr;
do {
const auto fh = curr->first;
const auto id = curr->second;
const auto ip = (id + 1) % 3;
const auto im = (id + 2) % 3;
const auto& p = fh->vertex(ip)->point().point();
const auto& q = fh->vertex(im)->point().point();
// std::cout << "ip, p: " << m_data.to_3d(support_plane_idx, p) << std::endl;
// std::cout << "im, q: " << m_data.to_3d(support_plane_idx, q) << std::endl;
CGAL_assertion(
fh->vertex(ip) == vhs[0] || fh->vertex(im) == vhs[0]);
if (fh->vertex(ip) == vhs[1]) {
if (is_debug) {
std::cout << "ip, found connecting edge: 2 " <<
m_data.to_3d(support_plane_idx, q) << " " <<
m_data.to_3d(support_plane_idx, p) << std::endl;
}
break;
}
if (fh->vertex(im) == vhs[1]) {
if (is_debug) {
std::cout << "im, found connecting edge: 2 " <<
m_data.to_3d(support_plane_idx, p) << " " <<
m_data.to_3d(support_plane_idx, q) << std::endl;
}
break;
}
++curr;
} while (curr != end);
const auto object = triangulation.dual(curr);
Segment_2 segment;
if (CGAL::assign(segment, object)) {
if (is_debug) {
std::cout << "found bisector: 2 " <<
m_data.to_3d(support_plane_idx, segment.source()) << " " <<
m_data.to_3d(support_plane_idx, segment.target()) << std::endl;
}
}
// Add iedge.
std::vector<Point_2> inter_points;
for (std::size_t i = 0; i < 4; ++i) {
const std::size_t ip = (i + 1) % 4;
const Segment_2 bbox_edge(wps[i].point(), wps[ip].point());
Point_2 inter_point;
if (KSR::intersection(segment, bbox_edge, inter_point)) {
inter_points.push_back(inter_point);
}
}
CGAL_assertion(inter_points.size() == 2);
if (is_debug) {
std::cout << "found iedge: 2 " <<
m_data.to_3d(support_plane_idx, inter_points[0]) << " " <<
m_data.to_3d(support_plane_idx, inter_points[1]) << std::endl;
}
const auto iv0 = m_data.igraph().
add_vertex(m_data.to_3d(support_plane_idx, inter_points[0])).first;
const auto iv1 = m_data.igraph().
add_vertex(m_data.to_3d(support_plane_idx, inter_points[1])).first;
const auto pair = m_data.igraph().add_edge(iv0, iv1, support_plane_idx);
const auto& iedge = pair.first;
const bool is_inserted = pair.second;
if (is_inserted) {
m_data.igraph().set_line(iedge, m_data.igraph().add_line());
}
m_data.support_plane(support_plane_idx).iedges().insert(iedge);
// CGAL_assertion_msg(false,
// "TODO: POLYGON SPLITTER, ADD BISECTORS!");
}
void dump(
@ -690,7 +802,7 @@ private:
}
template<typename Triangulation>
void dump_power_diagram(
void dump_power_cdt_and_diagram(
const Triangulation& tri,
const KSR::size_t support_plane_idx) {

View File

@ -137,6 +137,10 @@ int main (const int argc, const char** argv) {
// Real data tests.
assert(run_test("data/real-data-test/building_b_15squares_15planes.off", num_iters, num_tests));
// Coplanar tests.
// assert(run_test("data/edge-case-test/test-2-polygons.off", num_iters, num_tests));
// assert(run_test("data/edge-case-test/test-4-polygons.off", num_iters, num_tests));
std::cout << std::endl << "--OUTPUT STATS:" << std::endl;
std::cout << "* number of iterations per test: " << num_iters << std::endl;
std::cout << "* k intersections: {1,2,3,4,5,6,100}" << std::endl;