CGAL 4.4 Arrangement insert(arr,curve) crashes with some curves

人走茶凉 提交于 2019-12-10 11:24:10

问题


I tried to use Arrangement from CGAL, but for not clear reasons program crashes for some curves in CGAL 4.4 (not such problem in previous versions 4.3). Look at simple overview of problem, curve is outline of letter D, converted into line segments:

  dDouble dpts { 16.261, 95.267,  ... 95.267,  16.261, 95.267};
  dPoint pts = ... // converting to exact points with 3 decimal places
  Curve_2 cu = Curve_2(pts.begin(), pts.end());
  insert(arr, cu); // <----  here crash, supposed bug in CGAL 4.4  ------

Furthermore insert() also output empty line to stdout. I provide full example with cmake config file and output of program. System is running Linux Mint Petra.

Full program:


main.cpp


#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Cartesian.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arr_polyline_traits_2.h>
#include <CGAL/Arr_curve_data_traits_2.h>
#include <CGAL/Arrangement_with_history_2.h>
#include <CGAL/Arr_extended_dcel.h>
#include <CGAL/intersections.h>
#include <CGAL/Gmpq.h>

typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef typename Kernel::FT    Nt;
//***************************************************************
typedef CGAL::Aff_transformation_2<Kernel>              Aff_Transformation_2;
typedef CGAL::Point_2<Kernel>                           Point_2;
//***************************************************************
typedef CGAL::Arr_segment_traits_2<Kernel>              Segment_traits_2;
typedef CGAL::Arr_polyline_traits_2<Segment_traits_2>   Polyline_traits_2;
typedef Polyline_traits_2::Curve_2                      Curve_2;
typedef Polyline_traits_2                               Traits_2;  // renaming
typedef CGAL::Arr_extended_dcel<Traits_2, int, int, int> Dcel;
typedef CGAL::Arrangement_with_history_2<Traits_2, Dcel>  Arrangement_2;
//***************************************************************
typedef CGAL::Gmpq                                      Gmpq;
typedef std::deque<Point_2>    dPoint_2;
typedef std::deque<double>    dDouble;
#define   MULVAL    1000
inline int toInt(double d, int mul) { return int(d*mul + .5); }
inline Gmpq toGmpq(double d, int mul=MULVAL) { return Gmpq(toInt(d,mul), mul); }
inline Point_2 toPoint_2(double x, double y, int mul=MULVAL) { return Point_2( Nt(toGmpq(x,mul)),  Nt(toGmpq(y,mul))  ); }

int main() {
  // simple D letter outline
  dDouble dpts {     16.261, 95.267,  16.261, 48.027, 153.477, 48.027, 164.912, 49.104, 186.691, 51.458, 201.573, 54.251, 211.367, 56.921,
   225.415, 61.957, 238.134, 68.049, 249.204, 74.952, 258.604, 82.468, 266.944, 91.033, 272.727, 98.754, 277.419,107.216, 280.673,116.053,
   282.289,124.687, 282.364,132.995, 281.97, 136.238, 279.901,144.167, 276.218,152.181, 270.568,160.737, 262.216,170.448, 257.505,174.921,
   248.805,181.405, 237.688,187.749, 221.082,195.281, 218.006,196.525, 204.35, 201.024, 187.094,204.993, 183.018,205.735, 165.239,208.084,
   147.989,208.866,  16.261,208.866,  16.261,168.055,  38.329,167.772,  38.153, 95.267,  16.261, 95.267};

  dPoint_2 pts;
  for(int i=0;i<dpts.size()/2;i++) pts.push_back(toPoint_2(dpts[2*i],dpts[2*i+1])); // converting into exact points
  for(auto &p : pts) std::cout << p << " | "; std::cout << "\n";   // control output
  Arrangement_2    arr; // empty arrangement
  Curve_2 cu = Curve_2(pts.begin(), pts.end());

  insert(arr, cu); // bug in CGAL 4.4

  std::cout << "Working\n";
  return 0;
}

CMakeLists.txt


cmake_minimum_required(VERSION 2.8)
SET(CMAKE_VERBOSE_MAKEFILE ON)
set(XXX main)
project(XXX)
SET(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "-std=c++0x -frounding-math")
find_package(CGAL QUIET COMPONENTS Core )
include( ${CGAL_USE_FILE} )
add_executable(${XXX} ${XXX}.cpp)

Output: cmake .


-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
...
-- Using /usr/bin/c++ compiler.
-- Requested component: Core
-- Requested component: MPFR
-- Requested component: GMP
..

program output


16.261 95.267 | 16.261 48.027 | 153.477 48.027 | 164.912 49.104 | 186.691 51.458 | 201.573 54.251 | 211.367 56.921 | 225.415 61.957 | 
238.134 68.049 | 249.204 74.952 | 258.604 82.468 | 266.944 91.033 | 272.727 98.754 | 277.419 107.216 | 280.673 116.053 | 282.289 124.687 | 
282.364 132.995 | 281.97 136.238 | 279.901 144.167 | 276.218 152.181 | 270.568 160.737 | 262.216 170.448 | 257.505 174.921 | 248.805 181.405 | 
237.688 187.749 | 221.082 195.281 | 218.006 196.525 | 204.35 201.024 | 187.094 204.993 | 183.018 205.735 | 165.239 208.084 | 147.989 208.866 | 
16.261 208.866 | 16.261 168.055 | 38.329 167.772 | 38.153 95.267 | 16.261 95.267 | 

terminate called after throwing an instance of 'CGAL::Precondition_exception'
  what():  CGAL ERROR: precondition violation!
Expr: i != INVALID_INDEX
File: /usr/local/include/CGAL/Arr_polyline_traits_2.h
Line: 619
Aborted


回答1:


Indeed a bug in 4.4.

The patch bellow should fix it.

It will be fixed in the next official revision.

diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h
index 1a04d7d..aa48ded 100644
--- a/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h
+++ b/Arrangement_on_surface_2/include/CGAL/Arr_polyline_traits_2.h
@@ -2742,8 +2742,7 @@ namespace CGAL {
      *         If q is not in the x-range of cv, returns INVALID_INDEX.
      */
     template <typename Compare>
-    std::size_t locate_gen(const X_monotone_curve_2& cv,
-                            Compare compare) const
+    std::size_t locate_gen(const X_monotone_curve_2& cv, Compare compare) const
     {
       // The direction of cv. SMALLER means left-to-right and
       // otherwise right-to-left
@@ -2766,7 +2765,14 @@ namespace CGAL {
       Comparison_result res_to = compare(cv[to], ARR_MAX_END);
       if (res_to == EQUAL) return to;

-      if (res_to == res_from) return INVALID_INDEX;
+      // Check whether the point is either lexicographically to the left of
+      // the curve or lexicographically to the right of the curve.
+      if (res_to == res_from)
+        // If the x-monotone polyline is vertical, return the index of the
+        // segment that is closest to the point. Otherwise, the point is not
+        // in the x-range of the polyline.
+        return (is_vertical_2_object()(cv)) ?
+          ((res_to == SMALLER) ? from : to) : INVALID_INDEX;

       // Perform a binary search to locate the segment that contains q in its
       // range:


来源:https://stackoverflow.com/questions/24224960/cgal-4-4-arrangement-insertarr-curve-crashes-with-some-curves

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!