CGAL: Arrangement with Exact_circular_kernel_2 - cgal

I am trying to build an Arrangement of Circles using the Exact_circular_kernel_2. When I insert a Circle into the Arrangement, I get a segmentation fault.
This is my code:
CGAL::Circle_2< CGAL::Exact_circular_kernel_2 > circle1( CGAL::Point_2< CGAL::Exact_circular_kernel_2 >(1,1), 2 );
CGAL::Exact_circular_kernel_2::Circle_2 circle2 = circle1;
CGAL::Circular_arc_2< CGAL::Exact_circular_kernel_2 > arc( circle2 );
CGAL::Arr_circular_line_arc_traits_2< CGAL::Exact_circular_kernel_2 >::Curve_2 curve = arc;
CGAL::Arrangement_2< CGAL::Arr_circular_line_arc_traits_2< CGAL::Exact_circular_kernel_2 > > myArrangement;
cout<<curve<<endl;
cout<<myArrangement.is_valid()<<endl;
insert ( myArrangement, curve );
cout<<"done"<<endl;
The Code compiles without warnings and it doesn't matter whether I use circle1 or circle2 in line 3, the result is the same.
The program prints the following before the segmentation fault happens:
1/1 1/1 2/1 1 0 1/1 -1/1 2/1 1 1/1 0 1/1 -1/1 2/1 1 1/1
1
So the values of values of myArrangement and curve seem to be valid.
Any ideas what I'm doing wrong?
I am aware that I could use another Kernel, but I want to compare performances of different Kernels, so not using this Kernel wouldn't really be a solution.

I wasn't able to reproduce the problem.
Below is a slightly more clean version, but your version works on my platform as well, Ubuntu 12.04, g++ 4.6.3, CGAL 4.1 (or at least close to 4.1), What is yours?
#include <iostream>
#include <CGAL/Exact_circular_kernel_2.h>
#include <CGAL/Arr_circular_line_arc_traits_2.h>
#include <CGAL/Arrangement_2.h>
typedef CGAL::Exact_circular_kernel_2 Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Circle_2 Circle_2;
typedef CGAL::Arr_circular_line_arc_traits_2<Kernel> Traits;
typedef Traits::Curve_2 Curve_2;
typedef CGAL::Arrangement_2<Traits> Arrangement;
int main()
{
Circle_2 circle(Point_2(1,1), 2);
Curve_2 curve(circle);
Arrangement arr;
std::cout << curve << std::endl;
std::cout << arr.is_valid() << std::endl;
CGAL::insert(arr, curve);
std::cout << "done" << std::endl;
return 0;
}

Related

Numpy vs Eigen vs Xtensor Linear Algebra Benchmark Oddity

I recently was trying to compare different python and C++ matrix libraries against each other for their linear algebra performance in order to see which one(s) to use in an upcoming project. While there are multiple types of linear algebra operations, I have chosen to focus mainly on matrix inversion, as it seems to be the one giving strange results. I have written the following code below for the comparison, but am thinking I must be doing something wrong.
C++ Code
#include <iostream>
#include "eigen/Eigen/Dense"
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/xrandom.hpp>
#include <xtensor-blas/xlinalg.hpp> //-lblas -llapack for cblas, -llapack -L OpenBLAS/OpenBLAS_Install/lib -l:libopenblas.a -pthread for openblas
//including accurate timer
#include <chrono>
//including vector array
#include <vector>
void basicMatrixComparisonEigen(std::vector<int> dims, int numrepeats = 1000);
void basicMatrixComparisonXtensor(std::vector<int> dims, int numrepeats = 1000);
int main()
{
std::vector<int> sizings{1, 10, 100, 1000, 10000, 100000};
basicMatrixComparisonEigen(sizings, 2);
basicMatrixComparisonXtensor(sizings,2);
return 0;
}
void basicMatrixComparisonEigen(std::vector<int> dims, int numrepeats)
{
std::chrono::high_resolution_clock::time_point t1;
std::chrono::high_resolution_clock::time_point t2;
using time = std::chrono::high_resolution_clock;
std::cout << "Timing Eigen: " << std::endl;
for (auto &dim : dims)
{
std::cout << "Scale Factor: " << dim << std::endl;
try
{
//Linear Operations
auto l = Eigen::MatrixXd::Random(dim, dim);
//Eigen Matrix inversion
t1 = time::now();
for (int i = 0; i < numrepeats; i++)
{
Eigen::MatrixXd pinv = l.completeOrthogonalDecomposition().pseudoInverse();
//note this does not come out to be identity. The inverse is wrong.
//std::cout<<l*pinv<<std::endl;
}
t2 = time::now();
std::cout << "Eigen Matrix inversion took: " << std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1).count() * 1000 / (double)numrepeats << " milliseconds." << std::endl;
std::cout << "\n\n\n";
}
catch (const std::exception &e)
{
std::cout << "Error: '" << e.what() << "'\n";
}
}
}
void basicMatrixComparisonXtensor(std::vector<int> dims, int numrepeats)
{
std::chrono::high_resolution_clock::time_point t1;
std::chrono::high_resolution_clock::time_point t2;
using time = std::chrono::high_resolution_clock;
std::cout << "Timing Xtensor: " << std::endl;
for (auto &dim : dims)
{
std::cout << "Scale Factor: " << dim << std::endl;
try
{
//Linear Operations
auto l = xt::random::randn<double>({dim, dim});
//Xtensor Matrix inversion
t1 = time::now();
for (int i = 0; i < numrepeats; i++)
{
auto inverse = xt::linalg::pinv(l);
//something is wrong here. The inverse is not actually the inverse when you multiply it out.
//std::cout << xt::linalg::dot(inverse,l) << std::endl;
}
t2 = time::now();
std::cout << "Xtensor Matrix inversion took: " << std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1).count() * 1000 / (double)numrepeats << " milliseconds." << std::endl;
std::cout << "\n\n\n";
}
catch (const std::exception &e)
{
std::cout << "Error: '" << e.what() << "'\n";
}
}
}
This is compiled with:
g++ cpp_library.cpp -O2 -llapack -L OpenBLAS/OpenBLAS_Install/lib -l:libopenblas.a -pthread -march=native -o benchmark.exe
for OpenBLAS, and
g++ cpp_library.cpp -O2 -lblas -llapack -march=native -o benchmark.exe
for cBLAS.
g++ version 9.3.0.
And for Python 3:
import numpy as np
from datetime import datetime as dt
#import timeit
start=dt.now()
l=np.random.rand(1000,1000)
for i in range(2):
result=np.linalg.inv(l)
end=dt.now()
print("Completed in: "+str((end-start)/2))
#print(np.matmul(l,result))
#print(np.dot(l,result))
#Timeit also gives similar results
I will focus on the largest decade that runs in a reasonable amount of time on my computer: 1000x1000. I know that only 2 runs introduces a bit of variance, but I've run it with more and the results are roughly the same as below:
Eigen 3.3.9: 196.804 milliseconds
Xtensor/Xtensor-blas w/ OpenBlas: 378.156 milliseconds
Numpy 1.17.4: 172.582 milliseconds
Is this a reasonable result to expect? Why are the C++ libraries slower than Numpy? All 3 packages are using some sort of Lapack/BLAS backend, yet there is a significant difference between the 3. Particularly, Xtensor will pin my CPU to 100% usage with OpenBlas' threads, yet still manage to have worse performance.
I'm wondering if the C++ libraries are actually performing the inverse/pseudoinverse of the matrix, and if this is what is causing these results. In the commented sections of the C++ test code, I have noted that when I sanity-checked the results from both Eigen and Xtensor, the resulting matrix product between the matrix and its inverse was not even close to the identity matrix. I tried with smaller matrices (10x10) thinking it might be a precision error, but the problem remained. In another test, I test for rank, and these matrices are full rank. To be sure I wasn't going crazy, I tried with inv() instead of pinv() in both cases, and the results are the same. Am I using the wrong functions for this linear algebra benchmark, or is this Numpy twisting the knife on 2 disfunctional low level libraries?
EDIT:
Thank you everyone for your interest in this problem. I think I have figured out the issue. I suspect Eigen and Xtensor have lazy evaluation and this actually is causing errors downstream, and outputting random matrices instead of the inversed matrices. I was able to correct the strange numerical inversion failure with the following replacements in the code:
auto temp = Eigen::MatrixXd::Random(dim, dim);
Eigen::MatrixXd l(dim,dim);
l=temp;
and
auto temp = xt::random::randn<double>({dim, dim});
xt::xarray<double> l =temp;
However, the timings didn't change much:
Eigen 3.3.9: 201.386 milliseconds
Xtensor/Xtensor-blas w/ OpenBlas: 337.299 milliseconds.
Numpy 1.17.4: (from before) 172.582 milliseconds
Actually, a little strangely, adding -O3 and -ffast-math actually slowed down the code a little. -march=native had the biggest performance increase for me when I tried it. Also, OpenBLAS is 2-3X faster than CBLAS for these problems.
Firstly, you are not computing same things.
To compute inverse of l matrix, use l.inverse() for Eigen and xt::linalg::inv() for xtensor
When you link Blas to Eigen or xtensor, these operations are automatically dispatched to the your choosen Blas.
I tried replacing the inverse functions, replaced auto with MatrixXd and xt::xtensor to avoid lazy evaluation, linked openblas to Eigen, xtensor and numpy and compiled with only -O3 flag, the following are the results on my Macbook pro M1:
Eigen-3.3.9 (with openblas) - ~ 38 ms
Eigen-3.3.9 (without openblas) - ~ 85 ms
xtensor-master (with openblas) - ~41 ms
Numpy- 1.21.2 (with openblas) - ~35 ms.

How to copy a surface mesh in CGAL

I want to copy a mesh with the function copy_face_graph(source, target). But the target mesh is different (it has same number of vertices and faces, but the coordinates and the order are totally different).
The code:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <iostream>
#include <fstream>
#include <CGAL/boost/graph/copy_face_graph.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char* argv[]) {
const char* filename1 = (argc > 1) ? argv[1] : "data/blobby.off";
std::cout << ".off loaded" << std::endl;
std::ifstream input(filename1);
Mesh mesh_orig;
if (!input || !(input >> mesh_orig))
{
std::cerr << "First mesh is not a valid off file." << std::endl;
return 1;
}
input.close();
// ========================================================
Mesh mesh_copy;
CGAL::copy_face_graph(mesh_orig, mesh_copy);
// ========================================================
std::ofstream mesh_cpy("CPY_ANYLYZE/mesh_copy.off");
mesh_cpy << mesh_copy;
mesh_cpy.close();
return 0;
}
Dose anyone knows how to get a complete same mesh from the original mesh? Do I need add the named parameters, or maybe using another function?
Thanks a lot
Except if you intend to write some code working with different data structures, you can use the copy constructor from the Surface_mesh class, Mesh mesh_copy(mesh_orig). copy_face_graph does not do a raw copy because it works also if the input and output are of different types. However the output should be the same up to the order of the simplices.

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;
}

retrieve the index of point in CGAL

In the following code, a delaunay triangulation is made from an N dimensional array named points. Every element of this array has an index associated with it. For every vertex of the triangulation the nearest vertex is found correctly (without using the libraray: CGAL/Triangulation_vertex_base...). Now, I want to retrieve the index of each neighbor point with ->info(), but the way I've implemented that leads to error! How can I do that?
#include <vector>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
using namespace std();
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned int, Kernel> Vb;
typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> Triangulation;
typedef Triangulation::Edge_iterator Edge_iterator;
typedef Triangulation::Point Point;
typedef Triangulation::Vertex_handle Vertex_handle;
typedef Triangulation::Vertex_circulator Vertex_circulator;
typedef Kernel::Point_2 Point_2;
typedef std::vector<std::pair<Point_2, unsigned> > Vector;
const int N = 16;
int main(){
Vector points;
points.reserve(N);
.... {Some part of code which assignes values to dir[N][2]}
for (int i = 0; i < N; i++)
points.push_back(make_pair(Point_2(dir[i][0], dir[i][1]), i));\\ I want each point to have an index
Triangulation T;
T.insert(points.begin(), points.end());
cout << T.number_of_vertices() <<endl;
for(int i = 0; i < N; i++){
Vertex_handle handle = T.nearest_vertex(points[i]);
cout<<"incidents: \n" <<endl;
cout << handle->point() <<endl<<endl;
Vertex_circulator circulator = T.incident_vertices(handle), done(circulator);
do
{
if( !T.is_infinite ( circulator))
cout << circulator->point() << endl;
cout << circulator->point()->info()<<endl;
} while(++circulator != done);
}
return 0;}
edit: It seems that the origin of the error is primarily because of using the following kernel: typedef CGAL::Delaunay_triangulation_2 Triangulation;
error: no matching function for call to CGAL::Delaunay_triangulation_2 > >::nearest_vertex(std::pair, unsigned int>&)’
edit 2: when I print the output in two different lines, weired number(96) appears:
The code:
cout<<circulator->point()<<endl;
cout<<circulator->info()<<endl;
output(total number of points, 4):
3.26675 0.733887
2
96
2.02307 0.718587
1
2.33861 1.68862
3
when I print the information in one line, the number 96 disappears;
cout<<circulator->point()<<"\t"<<circulator->info()<<endl;
3.26675 0.733887 2
2.02307 0.718587 1
2.33861 1.68862 3

AbsoluteToNanoseconds vs AbsoluteToDuration

Apple has extremely comprehensive documentation, but I can't find any documentation for the function AbsoluteToNanoseconds? I was to find the difference between AbsoluteToNanoseconds and AbsoluteToDuration.
Note
I am beginning to think that the Apple Docs only cover Objective-C functions? Is this the case?
I found the following by using Apple-double-click:
Duration 32-bit millisecond timer for drivers
AbsoluteTime 64-bit clock
I'm not sure why it isn't documented anywhere, but here is an example of how it is used, if that helps:
static float HowLong(
AbsoluteTime endTime,
AbsoluteTime bgnTime
)
{
AbsoluteTime absTime;
Nanoseconds nanosec;
absTime = SubAbsoluteFromAbsolute(endTime, bgnTime);
nanosec = AbsoluteToNanoseconds(absTime);
return (float) UnsignedWideToUInt64( nanosec ) / 1000.0;
}
UPDATE:
"The main reason I am interested in the docs is to find out how it differs from AbsoluteToDuration"
That's easier. AbsoluteToNanoseconds() returns a value of type Nanoseconds, which is really an UnsignedWide struct.
struct UnsignedWide {
UInt32 hi;
UInt32 lo;
};
In contrast, AbsoluteToDuration() returns a value of type Duration, which is actually an SInt32 or signed long:
typedef SInt32 Duration;
Durations use a smaller, signed type because they are intended to hold relative times. Nanoseconds, on the other hand, only make sense as positive values, and they can be very large, since computers can stay running for years at a time.
According to https://developer.apple.com/library/prerelease/mac/releasenotes/General/APIDiffsMacOSX10_9/Kernel.html,
SubAbsoluteFromAbsolute(), along with apparently all the other *Absolute* functions, have been removed from Mavericks. I have confirmed this.
These functions are no longer necessary since at least in Mavericks and Mountain Lion (the two I tested), mach_absolute_time() already returns time in nanoseconds, and not in absolute form (which used to be the number of bus cycles), making a conversion no longer necessary. Thus, the conversion shown in clock_gettime alternative in Mac OS X and similar code presented in several places on the web, is no longer necessary. This can be confirmed on your system by checking that both the numerator and denominator returned by mach_timebase_info() are 1.
Here is my test code with lots of output to check if you need to do the conversion on your system (I have to perform a check since my code might run on older Macs, although I do the check at program initiation and set a function pointer to call a different routine):
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <time.h>
#include <iostream>
using namespace std;
int main()
{
uint64_t now, then;
uint64_t abs, nano;
mach_timebase_info_data_t timebase_info = {0,0};
then = mach_absolute_time();
sleep(1);
now = mach_absolute_time();
abs = now - then;
mach_timebase_info(&timebase_info);
cout << "numerator " << timebase_info.numer << " denominator "
<< timebase_info.denom << endl;
if ((timebase_info.numer != 1) || (timebase_info.denom != 1))
{
nano = (abs * timebase_info.numer) / timebase_info.denom;
cout << "Have a real conversion value" << endl;
}
else
{
nano = abs;
cout << "Both numerator and denominator are 1" << endl;
}
cout << "milliseconds = " << nano/1000000LL << endl;
}