corefine_and_compute_difference CGAL error: precondition violation - cgal

Problem description
I read the mesh from the file "blank.off" and load it into the a surface_mesh variable blank. One file named "hepoints49.txt" stores point clouds. I use function CGAL::advancing_front_surface_reconstruction() to convert this point cloud to surface_mesh sv, and then use function corefine_and_compute_difference(blank,sv,res) to perform the Boolean subtraction between blank and sv.But the program throws an exception and terminates. The following is displayed on the terminal:
Using context 4 . 3 GL
load sv...
Using context 4 . 3 GL
start difference...
CGAL error: precondition violation!
Expression : CGAL::is_valid_polygon_mesh(tm)
File : D:\dev\vcpkg\installed\x64-windows\include\CGAL/Polygon_mesh_processing/orientation.h
Line : 190
Could you please help me solve this problem?
code
#include<iostream>
#include<io.h>
#include<fstream>
#include<algorithm>
#include<array>
#include<CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include<CGAL/Advancing_front_surface_reconstruction.h>
#include<CGAL/Surface_mesh.h>
#include<CGAL/disable_warnings.h>
#include<CGAL/draw_surface_mesh.h>
#include<ctime>
#include<string>
#include<CGAL/polygon_mesh_processing/corefinement.h>
#include<CGAL/polygon_mesh_processing/remesh.h>
#include<CGAL/boost/graph/selection.h>
#include<CGAL/polygon_mesh_processing/repair_self_intersections.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
namespace PMP = CGAL::Polygon_mesh_processing;
typedef std::array<std::size_t, 3> Facet;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Mesh;
struct Construct {
Mesh& mesh;
template <typename PointIterator>
Construct(Mesh& mesh, PointIterator b, PointIterator e):mesh(mesh) {
for (; b != e; ++b) {
boost::graph_traits<Mesh>::vertex_descriptor v;
v = add_vertex(mesh);
mesh.point(v) = *b;
}
}
Construct& operator=(const Facet f) {
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::vertices_size_type size_type;
mesh.add_face(vertex_descriptor(static_cast<size_type>(f[0])),
vertex_descriptor(static_cast<size_type>(f[1])),
vertex_descriptor(static_cast<size_type>(f[2])));
return *this;
}
Construct& operator*() { return *this; }
Construct& operator++() { return *this; }
Construct& operator++(int) { return *this; }
};
int main() {
//load blank
Mesh blank, sv,res;
std::ifstream fin("blank.off");
fin>>blank;
fin.close();
CGAL::draw(blank);
//load sv
string filename = "hepoints49.txt" ;
std::cout << "load sv..."<< std::endl;
fin.open(filename);
std::vector<Point_3> points;
std::vector<Facet> facets;
std::copy(std::istream_iterator<Point_3>(fin),
std::istream_iterator<Point_3>(),
std::back_inserter(points));//load points
fin.close();
Construct construct(sv, points.begin(), points.end());
CGAL::advancing_front_surface_reconstruction(points.begin(), points.end(), construct);//convert sv to surface_mesh
CGAL::draw(sv);
std::cout << "start difference..." << std::endl;
bool valid_difference = PMP::corefine_and_compute_difference(blank,sv,res);
if (valid_difference) {
std::cout << "difference was successfully computed. " << std::endl;
CGAL::draw(res);
}
else {
std::cout << "difference could not be completed. Skip. " << endl << endl;
}
//CGAL::draw(res);
return 0;
}
Runtime environment
CGAL version: 5.3
IDE: VS2017
Solution Configuration: Debug x64
I tried to run this program in Release mode, of course there is no exception thrown. But the result I got turned out to be the opposite of what I want.
Files
Files that appearing in the code are provided below:
https://github.com/wenzaifou/for-stack-overflow-question3.git
Github link is provided because the file is relatively large.

The way the mesh is constructed from advancing front output does not filter out isolated vertices, which causes the exception to be raised. Adding a call to CGAL::Polygon_mesh_processing::remove_isolated_vertices(sv) will solve the problem.
Then you might encounter the issue that your meshes are not outward oriented (meaning then represent an infinite portion of space). Adding the following calls will solve the problem:
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(blank))
CGAL::Polygon_mesh_processing::reverse_face_orientations(blank);
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(sv))
CGAL::Polygon_mesh_processing::reverse_face_orientations(sv);
Doc refs here and there.

Related

CDT inserter and extractor operator problem

this question is a continuing of Error on Constrained Delaunay Triangulation and Gabriel Triangulations
Trying to write a minimal example for that problem I planned insert the triangulation
in a file (std::ofstream) using the << operator of CDT without calling the CGAL::make_conforming_Delaunay_2(cdt); or CGAL::make_conforming_Gabriel_2(cdt),
knowing that until this point everything occured OK.
The triangulation was created without problems and before the exit of the aplication I saved the triangulation in a file using the << operator of CDT. The file was saved without error.
When I tried to read the file using the >> operator of CDT an exception was raised (inside the >> operator). The text of exception is:
CGAL ERROR: assertion violation!\nExpr: s == LEFT_TURN\nFile: C:\\dev\\CGAL-5.3.1\\include\\CGAL\\Triangulation_2.h\nLine: 919
The code I wrote:
int main()
{
CDT cdt;
std::ifstream ArqSuperficie("trian.dtr"); This file was created with << operator of CDT
if (ArqSuperficie.good() == false)
{
return 1;
}
try()
{
ArqSuperficie >> cdt;
}
catch(std::exception& e)
{
std::cerr << "ERROR: exception " << e.what() << std::endl;
}
return 0;
}
Why CDT cannot read a file created by itself, of a triangulation that was created by itself without errors?
Based on the message of the exception I can´t have a clue of what is happening...
Thank you

How comes the lifetime of a local variable inside a function be extended?

See the code below. v1 is local variable inside a function. Accordingly, after leaving this fucntion, this variable should be killed. Thus, the move constructor should run into problem in the main function. But actually the outcome is the opposite. In the main function, I can see the contents of v1.
#include <iostream>
#include <vector>
using namespace std;
void my_fn(vector<vector<int>> & v) {
vector<int> v1 = {1, 2, 3};
v.push_back(move(v1));
cout << " " << endl;
}
int main(){
vector<vector<int>> v;
my_fn(v);
for(const auto & e:v)
for (const auto e1: e)
cout << e1 << endl;
return 0;
}
When you move the contents of v1 into v, v1 is not yet destroyed because that happens right before the closing bracket of the function my_fn. As a result, the contents of v1 are pushed into v which is taken by reference. The scope of v1 is not extended but its content is just copied.

CGAL example cannot read input files?

this is my first stackoverflow question, so I hope the following text meets the question requirements. If not, please tell me what needs to be changed so I can adapt the question.
I'm new to CGAL and C++ in general. I would like to use CGAL 5.0.2 on a Macbook Pro early 2015 with macOS Catalina Version 10.15.4.
So to begin with, I followed the instruction steps given by the CGAL documentation using the package manager Homebrew. Since CGAL is a header-only library I configured it using CMake, as is recommended by the documentation.
It all worked out fine, so I went on trying the recommended examples given in the file CGAL-5.0.2.tar.xz, which is provided here. I'm particularly interested in the example Voronoi_Diagram_2.
Using the Terminal I executed the command -DCGAL_DIR=$HOME/CGAL-5.0.2 -DCMAKE_BUILD_TYPE=Release . in the example folder called Voronoi_Diagram_2. Then I executed the command make. All went well, no error messages were prompted. But executing the resulting exec file didn't produce any results.
After some research I managed to modify the code in a way that it prints the values of some variables. Problem seems to be that the input file which contains the line segments for which the voronoi diagramm shall be calculated is not correctly read.
The while loop which I highlighted in the code below by inserting //// signs seems not to be entered. That's why I assume that the variable ifs is empty, even though the input file "data1.svd.cin", which can be found in the folder "data" of the example, wasn't.
Does anyone have an idea for the reasons of this behaviour? Any help is appreciated.
This is the vd_2_point_location_sdg_linf.cpp file included in the example, which I modified:
// standard includes
#include <iostream>
#include <fstream>
#include <cassert>
// includes for defining the Voronoi diagram adaptor
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Segment_Delaunay_graph_Linf_filtered_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_Linf_2.h>
#include <CGAL/Voronoi_diagram_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_adaptation_policies_2.h>
// typedefs for defining the adaptor
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Segment_Delaunay_graph_Linf_filtered_traits_2<K> Gt;
typedef CGAL::Segment_Delaunay_graph_Linf_2<Gt> DT;
typedef CGAL::Segment_Delaunay_graph_adaptation_traits_2<DT> AT;
typedef CGAL::Segment_Delaunay_graph_degeneracy_removal_policy_2<DT> AP;
typedef CGAL::Voronoi_diagram_2<DT,AT,AP> VD;
// typedef for the result type of the point location
typedef AT::Site_2 Site_2;
typedef AT::Point_2 Point_2;
typedef VD::Locate_result Locate_result;
typedef VD::Vertex_handle Vertex_handle;
typedef VD::Face_handle Face_handle;
typedef VD::Halfedge_handle Halfedge_handle;
typedef VD::Ccb_halfedge_circulator Ccb_halfedge_circulator;
void print_endpoint(Halfedge_handle e, bool is_src) {
std::cout << "\t";
if ( is_src ) {
if ( e->has_source() ) std::cout << e->source()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
} else {
if ( e->has_target() ) std::cout << e->target()->point() << std::endl;
else std::cout << "point at infinity" << std::endl;
}
}
int main()
{
std::ifstream ifs("data/data1.svd.cin");
assert( ifs );
VD vd;
Site_2 t;
// /////////// Inserted Comment ////////////////////////////////
std::cout << "In the following the insertion from ifs should take place" << std::flush;
// ///////////////// while loop which doesn't seem to be active //////////////////
while ( ifs >> t ) {
// Existing Code to insert the points in the voronoi structure
vd.insert(t);
// Inserted Code to check if while loop is entered
std::cout << "Entered while loop" << std::flush;
}
// ///////////////////////////////////////////////////////////////////////////////
ifs.close();
assert( vd.is_valid() );
std::ifstream ifq("data/queries1.svd.cin");
assert( ifq );
Point_2 p;
while ( ifq >> p ) {
std::cout << "Query point (" << p.x() << "," << p.y()
<< ") lies on a Voronoi " << std::flush;
Locate_result lr = vd.locate(p);
if ( Vertex_handle* v = boost::get<Vertex_handle>(&lr) ) {
std::cout << "vertex." << std::endl;
std::cout << "The Voronoi vertex is:" << std::endl;
std::cout << "\t" << (*v)->point() << std::endl;
} else if ( Halfedge_handle* e = boost::get<Halfedge_handle>(&lr) ) {
std::cout << "edge." << std::endl;
std::cout << "The source and target vertices "
<< "of the Voronoi edge are:" << std::endl;
print_endpoint(*e, true);
print_endpoint(*e, false);
} else if ( Face_handle* f = boost::get<Face_handle>(&lr) ) {
std::cout << "face." << std::endl;
std::cout << "The vertices of the Voronoi face are"
<< " (in counterclockwise order):" << std::endl;
Ccb_halfedge_circulator ec_start = (*f)->ccb();
Ccb_halfedge_circulator ec = ec_start;
do {
print_endpoint(ec, false);
} while ( ++ec != ec_start );
}
std::cout << std::endl;
}
ifq.close();
return 0;
}

OpenCL, simple vector addition but wrong output for large input

So, after spending hours reading and understanding I have finally made my first OpenCL program that actually does something, which is it adds two vectors and outputs to a file.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <fstream>
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
int main(int argc, char *argv[])
{
try
{
// get platforms, devices and display their info.
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
std::vector<cl::Platform>::iterator i=platforms.begin();
std::cout<<"OpenCL \tPlatform : "<<i->getInfo<CL_PLATFORM_NAME>()<<std::endl;
std::cout<<"\tVendor: "<<i->getInfo<CL_PLATFORM_VENDOR>()<<std::endl;
std::cout<<"\tVersion : "<<i->getInfo<CL_PLATFORM_VERSION>()<<std::endl;
std::cout<<"\tExtensions : "<<i->getInfo<CL_PLATFORM_EXTENSIONS>()<<std::endl;
// get devices
std::vector<cl::Device> devices;
i->getDevices(CL_DEVICE_TYPE_ALL,&devices);
int o=99;
std::cout<<"\n\n";
// iterate over available devices
for(std::vector<cl::Device>::iterator j=devices.begin(); j!=devices.end(); j++)
{
std::cout<<"\tOpenCL\tDevice : " << j->getInfo<CL_DEVICE_NAME>()<<std::endl;
std::cout<<"\t\t Type : " << j->getInfo<CL_DEVICE_TYPE>()<<std::endl;
std::cout<<"\t\t Vendor : " << j->getInfo<CL_DEVICE_VENDOR>()<<std::endl;
std::cout<<"\t\t Driver : " << j->getInfo<CL_DRIVER_VERSION>()<<std::endl;
std::cout<<"\t\t Global Mem : " << j->getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>()/(1024*1024)<<" MBytes"<<std::endl;
std::cout<<"\t\t Local Mem : " << j->getInfo<CL_DEVICE_LOCAL_MEM_SIZE>()/1024<<" KBbytes"<<std::endl;
std::cout<<"\t\t Compute Unit : " << j->getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>()<<std::endl;
std::cout<<"\t\t Clock Rate : " << j->getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>()<<" MHz"<<std::endl;
}
std::cout<<"\n\n\n";
//MAIN CODE BEGINS HERE
//get Kernel
std::ifstream ifs("vector_add_kernel.cl");
std::string kernelSource((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
std::cout<<kernelSource;
//Create context, select device and command queue.
cl::Context context(devices);
cl::Device &device=devices.front();
cl::CommandQueue cmdqueue(context,device);
// Generate Source vector and push the kernel source in it.
cl::Program::Sources sourceCode;
sourceCode.push_back(std::make_pair(kernelSource.c_str(), kernelSource.size()));
//Generate program using sourceCode
cl::Program program=cl::Program(context, sourceCode);
//Build program..
try
{
program.build(devices);
}
catch(cl::Error &err)
{
std::cerr<<"Building failed, "<<err.what()<<"("<<err.err()<<")"
<<"\nRetrieving build log"
<<"\n Build Log Follows \n"
<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices.front());
}
//Declare and initialize vectors
std::vector<cl_float>B(993448,1.3);
std::vector<cl_float>C(993448,1.3);
std::vector<cl_float>A(993448,1.3);
cl_int N=A.size();
//Declare and intialize proper work group size and global size. Global size raised to the nearest multiple of workGroupSize.
int workGroupSize=128;
int GlobalSize;
if(N%workGroupSize) GlobalSize=N - N%workGroupSize + workGroupSize;
else GlobalSize=N;
//Declare buffers.
cl::Buffer vecA(context, CL_MEM_READ_WRITE, sizeof(cl_float)*N);
cl::Buffer vecB(context, CL_MEM_READ_ONLY , (B.size())*sizeof(cl_float));
cl::Buffer vecC(context, CL_MEM_READ_ONLY , (C.size())*sizeof(cl_float));
//Write vectors into buffers
cmdqueue.enqueueWriteBuffer(vecB, 0, 0, (B.size())*sizeof(cl_float), &B[0] );
cmdqueue.enqueueWriteBuffer(vecB, 0, 0, (C.size())*sizeof(cl_float), &C[0] );
//Executing kernel
cl::Kernel kernel(program, "vector_add");
cl::KernelFunctor kernel_func=kernel.bind(cmdqueue, cl::NDRange(GlobalSize), cl::NDRange(workGroupSize));
kernel_func(vecA, vecB, vecC, N);
//Reading back values into vector A
cmdqueue.enqueueReadBuffer(vecA,true,0,N*sizeof(cl_float), &A[0]);
cmdqueue.finish();
//Saving into file.
std::ofstream output("vectorAdd.txt");
for(int i=0;i<N;i++) output<<A[i]<<"\n";
}
catch(cl::Error& err)
{
std::cerr << "OpenCL error: " << err.what() << "(" << err.err() <<
")" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
The problem is, for smaller values of N, I'm getting the correct result that is 2.6
But for larger values, like the one in the code above (993448) I get garbage output varying between 1 and 2.4.
Here is the Kernel code :
__kernel void vector_add(__global float *A, __global float *B, __global float *C, int N) {
// Get the index of the current element
int i = get_global_id(0);
//Do the operation
if(i<N) A[i] = C[i] + B[i];
}
UPDATE : Ok it seems the code is working now. I have fixed a few minor mistakes in my code above
1) The part where GlobalSize is initialized has been fixed.
2)Stupid mistake in enqueueWriteBuffer (wrong parameters given)
It is now outputting the correct result for large values of N.
Try to change the data type from float to double etc.

How to overload operator>> for bool

I want to parse scalar as bool.
This example works:
#include <yaml.h>
#include <iostream>
#include <sstream>
#include <string>
void operator>> (const YAML::Node & node, bool & b)
{
std::string tmp;
node >> tmp;
std::cout << tmp << std::endl;
b = (tmp == "1") || (tmp == "yes");
}
int main()
{
bool b1, b2;
std::stringstream ss("key: да\notherkey: no");
YAML::Parser parser(ss);
YAML::Node doc;
parser.GetNextDocument(doc);
doc["key"] >> b1;
doc["otherkey"] >> b2;
std::cout << b1 << std::endl;
std::cout << b2 << std::endl;
return 0;
}
But in more complicated case template operator is used:
YAML::operator>><bool> (node=..., value=#0x63f6e8) at /usr/include/yaml-cpp/nodeimpl.h:24
And I get 'YAML::InvalidScalar' if string in not 'yes' or 'no'.
yaml-cpp already reads bools by default, as specified by the YAML spec.
y, yes, true, on
produce true, and
n, no, false, off
produce false. If you want to extend or change this behavior (for example, so that "да" also produces true), as you found out, overloading operator >> in the YAML namespace works.
The reason it needs to be in the YAML namespace (but only for "more complicated examples" - meaning where you don't directly call operator >> with a bool argument) is the way C++ lookup works.
See this answer to my old question for a great explanation.