Skip to Content.
Sympa Menu

cgal-discuss - [cgal-discuss] Assertion failure doing collect_garbage() after removing isolated vertices from a surface mesh

Subject: CGAL users discussion list

List archive

[cgal-discuss] Assertion failure doing collect_garbage() after removing isolated vertices from a surface mesh


Chronological Thread 
  • From: Yaoyu Hu <>
  • To:
  • Subject: [cgal-discuss] Assertion failure doing collect_garbage() after removing isolated vertices from a surface mesh
  • Date: Thu, 2 Dec 2021 00:07:17 -0500
  • Authentication-results: mail2-smtp-roc.national.inria.fr; spf=None ; spf=Pass ; spf=None
  • Ironport-data: A9a23:8ZAMQahOrXtf0uWNZfmhCDoNX161CBEKZh0ujC45NGQNrF6WrkVWyGsbUW/XOvneNmf3eo0nbY/k9RgP7JODnYVkTVBo/lhgHilAwSbnLYTAfx2oZ0t+DeWaERk5t51GAjX4wXFdokb0/n9BCZC86ykjvU20buCkUredYHgrHVYMpBoJ0HqPpcZp2uaEvvDiW2thifuqyyHuEAfNNwxcagr42IrfwP9bh8kejRtD1rAIiV+ni3eF/5UdJMp3yahctBIUSKEMdgKxb76rIL1UYgrkExkR5tONyt4Xc2UPS7/WeBCB0z9YAvf/xBdFoSM23+AwM/90hUV/0W3Y2YAsjo8U6NrpFlpB0q7kwIzxVzFYDjB3Orxboe6Xf1CwtMWSywvNdH6EL/BGUx5tZ9RBoI6bBkkXraBCQNwXVTiIiOuyhb66UeJxnd8LN9juJIpZu3d6zDifA+xOfHxpa7GSsIUegyNp05gIReKEMpJfM2s+NQCbNkUJZ0NIXbsguMytolX/VxxRjm6PgZQ2xnyKlFkvlOf5WDbOUtmDRMEQhknB42yfoDm/DRYdO9iSjzGC9xqRaib0tXuTcOov+HeQr5aGQWF/x1D/zDUTXFq/5OG20wuwAo0CbUMT/SUqoO4580nDohzVN/GniCbsg/Lec4M4/y4GBMWlxa/d4gLfDW8BJtKEQMJzr9c4HFTGyXfQ9+4ExlVTXHm9RneU97PSpjS3UcTQBQfuegdcJTY4DxLfTE3fQ/4BohuP0EJ4szEtJQzN/g==
  • Ironport-hdrordr: A9a23:zXd3Iq7cgH3wVv25RAPXwMXXdLJyesId70hD6qkRc20zTiX8raqTdZsgpHzJYVoqOE3I+urgBEDjewK/yXcd2+B4VotKNzOW3VdAQrsSibcKAAeNJ8Q9zINgPGtbHJSWweefMWRH
  • Ironport-phdr: A9a23:G6ulDhI8aN8hVnhLvNmcuAJhWUAX0o4c3iYr45Yqw4hDbr6kt8y7ehCFvLMz0BSWDM3y0LFts6LuqafuWGgNs96qkUspV9hybSIDktgchAc6AcSIWgXRJf/uaDEmTowZDAc2t360PlJIF8ngelbcvmO97SIIGhX4KAF5Ovn5FpTdgsipyuy+4ZzebgpHiDe/Zb55MQm7oxjWusQKm4VpN7w/ygHOontGeuRWwX1nKFeOlBvi5cm+4YBu/T1It/0u68BPX6P6f78lTbNDFzQpL3o15MzwuhbdSwaE+2YRXX8XkhpMBAjF8Q36U5LsuSb0quZxxC+XNtDxQr4pRDSi9L9rRwH0hycbOTA592TXhdZxjKJdvRmtoxNyzorRbIyTM/Vwf6bdcskbRWpFR8pdTjZPAoO9b4sUD+oBPOBYr4bkq1UQohayGAmhCPryxjJJm3T62aM33/g9HQ3D2gErAtAAv2nOrNjtO6gcUe67wqrVwzvdc/xbwi3y5JTSfx07vf2AQbB9fMzMwkcvDQPFiVCQpJTnMDyP0eQMs3Wb5PdiW+KylmUqrAFxoiWvx8g2jYnIhp8Vxk3A+Ch6wYs4PtK4SEthbt6lFJtcrT2VN4xzQs47RWxjpSk1xKEct5GhYCgK1IooxwTZa/GfcIWE/xztWeSRLDp2mH9oZrOyiwiy/EW91+HxSse63VRFoydEj9TCuG0A2wDX58WGSvVz8Umv1DSO2g3O9+xJJUY5nrfVJZ4mx74/jJsTsULbEy/5mUX2kK+Wdlg/9eSy9+vnZbDmqoeTN49zjQH+PaAuldKlDeskNQgOWm6W8vm/2r375UD1XqlGg/ksnqTasJ3WP9oXqrO5DgNPz4ou6RayAjG729oCh3YHNkhKeBefgojpJV7OJPf4AO+6g1u2kTdrw+nKPqXuApnQN3TDnqrtcLR95kJGxwozytdf551QCr4fOv78RkjxtNnAAh84NQy73frnBc1j2o8CXW+DGKyUPaPIvVOW++4iI/OAaJIXtTv9M/Ql4uThjX49mV8TZ6mp2p4XZWi4HvR7I0SWe33sg9ccEWsXugczT+3nhUaNUT5WfXmyXqY86isnB4KhCIfPXpqtj6CZ3CenAp1WYXhLBUyDEXjyc4WIQuoDaCOJIsB9jzwETqOhRpQ61RCusQ/606BoIvDV+i0er5Lj1cJ66/fdlREopnRICJGW3GiJCm11hWgVXCQe3aZloEU7xE3Q/7J/hqlpHNtC+rtpT09uNYPNxutrFomjClzpcdKASVLgSdKjV2JiBuktysMDNh8uU+6piQrOinH2Utf9dpSODZ0wt7rThj3/fpkgjXnB06Ylgh8tRc4dbQVOaYZw8gHSA8jClEDLzs5CkIwT2SfM8CGIym/c5Cll

Hi,

I am trying to fix and clear some issues from a surface mesh. I do the following three steps in sequence: 
(1) Duplicate non-manifold vertices.
(2) Remove self-intersections. And,
(3) Remove isolated vertices.
(4) Remove small connected components.

I always get an assertion error in (4). In my code, (1), (3), and (4) are directly calling CGAL functions to do the job. For (2) I have a simple procedure where I first identify all the self-intersection pairs and then remove all the faces that have self-intersection. I have set up a sample code and a sample mesh. The code is also available as a GitHub Gist 
https://gist.github.com/huyaoyu/c10ff67a2fe67c141af77142e475a83d

The sample mesh is saved in my personal Google Drive.
https://drive.google.com/drive/folders/1AmQONiss-q26cgs4wNBp3fMSlVmo09Ej?usp=sharing

I am using CGAL 5.3 on Ubuntu 20.04.

=== Code begins. ===

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>

#include <CGAL/Surface_mesh/IO/PLY.h>

#include <CGAL/Polygon_mesh_processing/connected_components.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>

namespace PMP = CGAL::Polygon_mesh_processing;

typedef CGAL::Simple_cartesian<float> Kernel_t;
typedef Kernel_t::Point_3  Point_t;

typedef CGAL::Surface_mesh<Point_t> Mesh_t;

typedef Kernel_t::Compare_dihedral_angle_3 Compare_dihedral_angle_3;

template < typename MeshT >
void read_mesh(const std::string& fn, MeshT& mesh) {
    std::ifstream ifs(fn, std::ios::binary);

    if ( !ifs ) {
        std::stringstream ss;
        ss << "Cannot open " << fn;
        throw std::runtime_error(ss.str());
    }

    std::string comments;
    CGAL::IO::read_PLY(ifs, mesh, comments);
}

template < typename MeshT >
void duplicate_non_manifold_vertices(MeshT& mesh) {
    PMP::duplicate_non_manifold_vertices(mesh);
}

template < typename MeshT >
int remove_self_intersections( MeshT& mesh ) {
    typedef typename boost::graph_traits<MeshT>::face_descriptor Face_t;

    std::vector< std::pair< Face_t, Face_t > > intersections;
    PMP::self_intersections<CGAL::Parallel_if_available_tag>(
        faces(mesh),
        mesh,
        std::back_inserter(intersections)
    );

    const int n_intersections = intersections.size();
    if ( n_intersections > 0 ) {
        for ( const auto& inter_pair : intersections ) {
            mesh.remove_face( inter_pair.first );
            mesh.remove_face( inter_pair.second );
        }

        mesh.collect_garbage();
    }

    return n_intersections;
}

template < typename MeshT >
int remove_isolated_vertices( MeshT& mesh ) {
    const int N = PMP::remove_isolated_vertices(mesh);
    return N;
}

// For computing the connected components.
template < typename MeshT >
struct ConnectionConstraint : public boost::put_get_helper< bool, ConnectionConstraint<MeshT> > {
    typedef typename boost::graph_traits<MeshT>::edge_descriptor EdgeT;

    typedef boost::readable_property_map_tag category;
    typedef bool                             value_type;
    typedef bool                             reference;
    typedef EdgeT                            key_type;

    ConnectionConstraint()
    : m_mesh(nullptr) {}

    ConnectionConstraint( MeshT& mesh, double bound )
    : m_mesh(&mesh), m_bound(bound) {}

    bool operator[] ( EdgeT edge ) const {
        const MeshT& mesh = *m_mesh;
        return m_compare(
            mesh.point( source( edge, mesh ) ),
            mesh.point( target( edge, mesh ) ),
            mesh.point( target( next( halfedge( edge, mesh ), mesh ), mesh ) ),
            mesh.point( target( next( opposite( halfedge( edge, mesh ), mesh), mesh ) ,mesh ) ),
            m_bound ) == CGAL::SMALLER;
    }

    const MeshT* m_mesh;
    Compare_dihedral_angle_3 m_compare;
    double m_bound;
};

template < typename MeshT >
void remove_small_connected_components(
    MeshT& mesh,
    int limit_num=10,
    double limit_di_angle_rad=2.36 /* 3/4 pi */ ) {
   
    const double bound = std::cos( limit_di_angle_rad );

    PMP::keep_large_connected_components(
        mesh,
        limit_num,
        PMP::parameters::edge_is_constrained_map(
            ConnectionConstraint<MeshT>(mesh, bound) )
    );
}

int main(int argc, char** argv) {
    const std::string in_mesh_fn =
        "please download from https://drive.google.com/drive/folders/1AmQONiss-q26cgs4wNBp3fMSlVmo09Ej?usp=sharing";
   
    // Read the mesh.
    Mesh_t mesh;
    read_mesh( in_mesh_fn, mesh );

    // Duplicate non-manifold_vertices.
    duplicate_non_manifold_vertices(mesh);

    // Remove self-intersection faces.
    remove_self_intersections(mesh);

    // Remove isolated vertices.
    remove_isolated_vertices(mesh);

    // Remove small connected components.
    remove_small_connected_components(mesh);
   
    return 0;
}

=== Code ends. ===

Step (2) is the remove_self_intersections() function. The assertion error shows in my terminal is

===  Terminal output begins. ===

terminate called after throwing an instance of 'CGAL::Assertion_exception'
  what():  CGAL ERROR: assertion violation!
Expr: _idx < data_.size()
File: /usr/local/include/CGAL/Surface_mesh/Properties.h
Line: 193

=== Terminal output ends. ===

I have also saved the backtrace from GDB in the Google Drive folder (a txt and a screenshot). please download from https://drive.google.com/drive/folders/1AmQONiss-q26cgs4wNBp3fMSlVmo09Ej?usp=sharing

From the backtrace, it looks like when iterating through the faces of the mesh for computing the connected components, a face descriptor is out of the valid range.

Another thing that I found during the debugging is that, if you check the output of mesh.has_garbage() after calling PMP::remove_isolated_vertices() in my remove_isolated_vertices() function, mesh.has_garbage() is true. I suppose  PMP::remove_isolated_vertices() should not leave the mesh in a state where it has uncollected garbage.

Any help is appreciated!

Thank you!

Yaoyu




Archive powered by MHonArc 2.6.19+.

Top of Page