bool test(const Arrangement_2& arr)
{
  if (arr.number_of_vertices() != 0) {
    std::cerr << "(A) Number of vertices (" << arr.number_of_vertices()
              << ") not 0!" << std::endl;
    return false;
  }

  // Check the validity more thoroughly.
  if (! CGAL::is_valid(arr)) {
    std::cerr << "The arrangement is NOT valid!" << std::endl;
    return false;
  }

  return true;
}
示例#2
0
int main (int argc, char *argv[])
{
  // Get the name of the input file from the command line, or use the default
  // fan_grids.dat file if no command-line parameters are given.
  const char * filename = (argc > 1) ? argv[1] : "fan_grids.dat";

  // Open the input file.
  std::ifstream     in_file (filename);

  if (! in_file.is_open()) {
    std::cerr << "Failed to open " << filename << " ..." << std::endl;
    return (1);
  }

  // Read the segments from the file.
  // The input file format should be (all coordinate values are integers):
  // <n>                                 // number of segments.
  // <sx_1> <sy_1>  <tx_1> <ty_1>        // source and target of segment #1.
  // <sx_2> <sy_2>  <tx_2> <ty_2>        // source and target of segment #2.
  //   :      :       :      :
  // <sx_n> <sy_n>  <tx_n> <ty_n>        // source and target of segment #n.
  
  std::list<Segment_2>  segments;

  unsigned int n;
  in_file >> n;
  unsigned int i;
  for (i = 0; i < n; ++i) {
    int sx, sy, tx, ty;
    in_file >> sx >> sy >> tx >> ty;
    segments.push_back (Segment_2 (Point_2 (Number_type(sx), Number_type(sy)),
                                   Point_2 (Number_type(tx), Number_type(ty))));
  }
  in_file.close();

  // Construct the arrangement by aggregately inserting all segments.
  Arrangement_2                  arr;
  CGAL::Timer                    timer;

  std::cout << "Performing aggregated insertion of " 
            << n << " segments." << std::endl;

  timer.start();
  insert (arr, segments.begin(), segments.end());
  timer.stop();

  // Print the arrangement dimensions.
  std::cout << "V = " << arr.number_of_vertices()
	    << ",  E = " << arr.number_of_edges() 
	    << ",  F = " << arr.number_of_faces() << std::endl;

  std::cout << "Construction took " << timer.time() 
	    << " seconds." << std::endl;
  
  return 0;
}
示例#3
0
int main (int argc, char *argv[])
{
  // Get the name of the input file from the command line, or use the default
  // Bezier.dat file if no command-line parameters are given.
  const char   *filename = (argc > 1) ? argv[1] : "Bezier.dat";

  // Open the input file.
  std::ifstream   in_file (filename);

  if (! in_file.is_open()) {
    std::cerr << "Failed to open " << filename << std::endl;
    return 1;
  }

  // Read the curves from the input file.
  unsigned int               n_curves;
  std::list<Bezier_curve_2>  curves;
  Bezier_curve_2             B;
  unsigned int               k;
  
  in_file >> n_curves;
  for (k = 0; k < n_curves; k++) {
    // Read the current curve (specified by its control points).
    in_file >> B;
    curves.push_back (B);

    std::cout << "B = {" << B << "}" << std::endl;
  }

  // Construct the arrangement.
  Arrangement_2                     arr;
  insert (arr, curves.begin(), curves.end());

  // Print the arrangement size.
  std::cout << "The arrangement size:" << std::endl
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges() 
            << ",  F = " << arr.number_of_faces() << std::endl;

  return 0;
}
示例#4
0
int main()
{
    // Construct the arrangement of five intersecting segments.
    Arrangement_2  arr;
    Walk_pl        pl(arr);

    Segment_2      s1(Point_2(1, 0), Point_2(2, 4));
    Segment_2      s2(Point_2(5, 0), Point_2(5, 5));
    Segment_2      s3(Point_2(1, 0), Point_2(5, 3));
    Segment_2      s4(Point_2(0, 2), Point_2(6, 0));
    Segment_2      s5(Point_2(3, 0), Point_2(5, 5));

    insert_non_intersecting_curve(arr, s1, pl);
    insert_non_intersecting_curve(arr, s2, pl);
    insert(arr, s3, pl);
    insert(arr, s4, pl);
    insert(arr, s5, pl);

    // Print the size of the arrangement.
    std::cout << "The arrangement size:" << std::endl
              << "   V = " << arr.number_of_vertices()
              << ",  E = " << arr.number_of_edges()
              << ",  F = " << arr.number_of_faces() << std::endl;

    // Perform a point-location query on the resulting arrangement and print
    // the boundary of the face that contains it.
    Point_2 q(4, 1);
    Walk_pl::result_type obj = pl.locate(q);

    Arrangement_2::Face_const_handle  f;
    CGAL_assertion_code(bool success =) CGAL::assign(f, obj);

    CGAL_assertion(success);
    std::cout << "The query point (" << q << ") is located in: ";
    print_face<Arrangement_2>(f);

    return 0;
}
void CriticalCurves::setParameters(double radius_1, double radius_2, Arrangements_2 insets_1, Arrangements_2 insets_2)
{
    Arrangement_2_iterator inset_1 = insets_1.begin();
    Arrangement_2_iterator inset_2 = insets_2.begin();

    while (inset_1 != insets_1.end() && inset_2 != insets_2.end())
    {
        Arrangement_2 arrangement;

        // Add the curves of the inset.
        for (Edge_iterator edge = inset_1->edges_begin(); edge != inset_1->edges_end(); ++edge)
        {
            insert(arrangement, edge->curve());
        }

        // Add the critical curves of type I.
        for (Edge_iterator edge = inset_2->edges_begin(); edge != inset_2->edges_end(); ++edge)
        {
            if (CGAL::COLLINEAR == edge->curve().orientation())
            {
                // Displaced a segment.
                Nt_traits nt_traits;
                Algebraic_ft factor = nt_traits.convert(Rational(radius_1) + Rational(radius_2));
                Conic_point_2 source = edge->curve().source();
                Conic_point_2 target = edge->curve().target();
                Algebraic_ft delta_x = target.x() - source.x();
                Algebraic_ft delta_y = target.y() - source.y();
                Algebraic_ft length = nt_traits.sqrt(delta_x * delta_x + delta_y * delta_y);
                Algebraic_ft translation_x = factor * delta_y / length;
                Algebraic_ft translation_y = - factor * delta_x / length;
                Conic_point_2 point_1(source.x() + translation_x, source.y() + translation_y);
                Conic_point_2 point_2(target.x() + translation_x, target.y() + translation_y);
                Algebraic_ft a = - delta_y;
                Algebraic_ft b = delta_x;
                Algebraic_ft c = factor * length - (source.y() * target.x() - source.x() * target.y());
                X_monotone_curve_2 x_monotone_curve(a, b, c, point_1, point_2);
                insert(arrangement, x_monotone_curve);
            }
            else
            {
                // Displaces an arc.
                Rational two(2);
                Rational four(4);

                Rational r = edge->curve().r();
                Rational s = edge->curve().s();
                Rational t = edge->curve().t();
                Rational u = edge->curve().u();
                Rational v = edge->curve().v();
                Rational w = edge->curve().w();

                Nt_traits nt_traits;
                Rational x_center = - u / (two * r);
                Rational y_center = - v / (two * r);
                Rat_point_2 rat_center(x_center, y_center);
                Conic_point_2 center(nt_traits.convert(x_center), nt_traits.convert(y_center));

                Rational radius = Rational(radius_1) + two * Rational(radius_2);

                Algebraic_ft coefficient = nt_traits.convert(radius / Rational(radius_2));

                Conic_point_2 source_1 = edge->curve().source();
                Algebraic_ft x_source_2 = center.x() + coefficient * (source_1.x() - center.x());
                Algebraic_ft y_source_2 = center.y() + coefficient * (source_1.y() - center.y());
                Conic_point_2 source_2(x_source_2, y_source_2);

                Conic_point_2 target_1 = edge->curve().target();
                Algebraic_ft x_target_2 = center.x() + coefficient * (target_1.x() - center.x());
                Algebraic_ft y_target_2 = center.y() + coefficient * (target_1.y() - center.y());
                Conic_point_2 target_2(x_target_2, y_target_2);

                Rat_circle_2 circle(rat_center, radius * radius);

                Conic_arc_2 conic_arc(circle, CGAL::COUNTERCLOCKWISE, source_2, target_2);

                insert(arrangement, conic_arc);
            }
        }

        // Add the critical curves of type II.
        for (Edge_iterator edge = inset_2->edges_begin(); edge != inset_2->edges_end(); ++edge)
        {
            double x = CGAL::to_double(edge->curve().source().x());
            double y = CGAL::to_double(edge->curve().source().y());
            double radius = radius_1 + radius_2;
            Rat_point_2 center(x, y);
            Rat_circle_2 circle(center, radius * radius);
            Conic_arc_2 conic_arc(circle);
            insert(arrangement, conic_arc);
        }

        // Remove the curves which are not include in the inset.
        Objects objects;
        Face_handle face;
        for (Edge_iterator edge = arrangement.edges_begin(); edge != arrangement.edges_end(); ++edge)
        {
            CGAL::zone(*inset_1, edge->curve(), std::back_inserter(objects));
            for (Object_iterator object = objects.begin(); object != objects.end(); ++object)
            {
                if (assign(face, *object))
                {
                    if (face->is_unbounded())
                    {
                        remove_edge(arrangement, edge);
                        break;
                    }
                }
            }
            objects.clear();
        }

        // Print essential information on the standard input.
        std::cout << "Arrangement:" << std::endl;
        std::cout << "  Number of vertices: " << arrangement.number_of_vertices() << std::endl;
        std::cout << "  Number of edges   : " << arrangement.number_of_edges() << std::endl;
        std::cout << "  Number of face    : " << arrangement.number_of_faces() << std::endl;

        this->critical_curves.push_back(arrangement);

        ++inset_1;
        ++inset_2;
    }

    // Commit changes.
    emit(criticalCurvesChanged());
    return;
}
int main()
{
  Arrangement_2 arr;

  // Construct an arrangement of five linear objects.
  std::vector<X_monotone_curve_2>  curves;
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(0, 1)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(1, 0)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(0, -1)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(-1, 0)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(1, 1)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(1, -1)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(-1, 1)));
  curves.push_back(Ray_2(Point_2(0, 0), Point_2(-1, -1)));

  std::vector<Halfedge_handle> hhs(curves.size());
  for (size_t i = 0; i < curves.size(); i++)
    hhs[i] = insert_non_intersecting_curve(arr, curves[i]);
  bool valid = arr.is_valid();
  std::cout << "Arrangement size:"
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges()
            << ",  F = " << arr.number_of_faces() << std::endl;
  std::cout << "The arrangement is "
            << (valid ? "valid." : "NOT valid!") << std::endl;
  if (! valid) return (1);

  // Remove the edges.
  for (size_t i = 0; i < hhs.size(); i++) {
    arr.remove_edge(hhs[i]);
    bool valid = arr.is_valid();
    std::cout << "  Removed " << i+1 << " curve(s), arrangement is "
              << (valid ? "valid." : "NOT valid!") << std::endl;

    if (! valid) return (1);
  }

  std::cout << "Final arrangement size:"
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges()
            << ",  F = " << arr.number_of_faces() << std::endl;

  if (!::test(arr)) return 1;

  /* Construct another arrangement of a segment connected to a ray.
   * First remove the ray, then remove the segment.
   *
   *  o---------------o
   *  |               |
   *  |               |
   *  |               |
   *  |       o--o----|
   *  |               |
   *  |               |
   *  |               |
   *  o---------------o
   */
  if (!test_ray(arr, arr.unbounded_face())) return 1;

  /* Construct another arrangement of a segment connected to a ray.
   * First remove the ray, then remove the segment.
   *
   *  o---------------o
   *  |               |
   *  |               |
   *  |               |
   *  |       o--o----|
   *  |               |
   *  o---------------o
   *  |               |
   *  o---------------o
   */
  Line_2 l1(Point_2(0, -1), Point_2(1, -1));
  Halfedge_handle eh1 =
    arr.insert_in_face_interior(X_monotone_curve_2(l1), arr.unbounded_face());

  if (!test_ray(arr, eh1->face())) return 1;
  arr.remove_edge(eh1);

  /* Construct another arrangement of a segment connected to a ray.
   * First remove the ray, then remove the segment.
   *
   *  o-----o---------o
   *  |     |         |
   *  |     |         |
   *  |     |         |
   *  |     | o--o----|
   *  |     |         |
   *  |     |         |
   *  |     |         |
   *  o-----o---------o
   */
  Line_2 l2(Point_2(-1, 0), Point_2(-1, 1));
  Halfedge_handle eh2 =
    arr.insert_in_face_interior(X_monotone_curve_2(l2), arr.unbounded_face());

  if (!test_ray(arr, eh2->twin()->face())) return 1;
  arr.remove_edge(eh2);

  return 0;
}
示例#7
0
int main()
{
  Arrangement_2   arr;

  // Construct an arrangement of seven intersecting line segments.
  // We keep a handle for the vertex v_0 that corresponds to the point (1,1).
  Arrangement_2::Halfedge_handle  e =
    insert_non_intersecting_curve (arr, Segment_2 (Point_2 (1, 1),
                                                   Point_2 (7, 1)));
  Arrangement_2::Vertex_handle    v0 = e->source();
  insert (arr, Segment_2 (Point_2 (1, 1), Point_2 (3, 7)));
  insert (arr, Segment_2 (Point_2 (1, 4), Point_2 (7, 1)));
  insert (arr, Segment_2 (Point_2 (2, 2), Point_2 (9, 3)));
  insert (arr, Segment_2 (Point_2 (2, 2), Point_2 (4, 4)));
  insert (arr, Segment_2 (Point_2 (7, 1), Point_2 (9, 3)));
  insert (arr, Segment_2 (Point_2 (3, 7), Point_2 (9, 3)));

  // Create a mapping of the arrangement vertices to indices.
  CGAL::Arr_vertex_index_map<Arrangement_2>        index_map_tmp(arr);
  boost::Arr_vertex_index_map_boost<Arrangement_2> index_map(index_map_tmp);

  // Perform Dijkstra's algorithm from the vertex v0.
  Edge_length_func                                      edge_length;

  boost::vector_property_map<double, boost::Arr_vertex_index_map_boost<Arrangement_2> > dist_map(static_cast<unsigned int>(arr.number_of_vertices()), index_map);
  boost::dijkstra_shortest_paths(arr, v0,
                                 boost::vertex_index_map(index_map).
                                 weight_map(edge_length).
                                 distance_map(dist_map));

  // Print the results:
  Arrangement_2::Vertex_iterator      vit;

  std::cout << "The distances of the arrangement vertices from ("
            << v0->point() << ") :" << std::endl;
  for (vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit)
    std::cout << "(" << vit->point() << ") at distance "
              << dist_map[vit] << std::endl;

  return 0;
}
示例#8
0
int main()
{
  std::list<Curve_2>  curves;

  // Create a circle centered at the origin with squared radius 2.
  Kernel::Point_2 c1 = Kernel::Point_2(0, 0);
  Circle_2 circ1 = Circle_2(c1, CGAL::Exact_rational(2));

  curves.push_back(Curve_2(circ1));

  // Create a circle centered at (2,3) with radius 3/2 - note that
  // as the radius is rational we use a different curve constructor.
  Kernel::Point_2 c2 = Kernel::Point_2(2, 3);

  curves.push_back(Curve_2(c2, CGAL::Exact_rational(3, 2)));

  // Create a segment of the line (y = x) with rational endpoints.
  Kernel::Point_2 s3 = Kernel::Point_2(-2, -2);
  Kernel::Point_2 t3 = Kernel::Point_2(2, 2);
  Segment_2 seg3 = Segment_2(s3, t3);

  curves.push_back(Curve_2(seg3));

  // Create a line segment with the same supporting line (y = x), but
  // having one endpoint with irrational coefficients.
  CoordNT sqrt_15 = CoordNT(0, 1, 15); // = sqrt(15)
  Point_2 s4 = Point_2(3, 3);
  Point_2 t4 = Point_2(sqrt_15, sqrt_15);

  curves.push_back(Curve_2(seg3.supporting_line(), s4, t4));

  // Create a circular arc that correspond to the upper half of the
  // circle centered at (1,1) with squared radius 3. We create the
  // circle with clockwise orientation, so the arc is directed from
  // (1 - sqrt(3), 1) to (1 + sqrt(3), 1).
  Kernel::Point_2 c5 = Kernel::Point_2(1, 1);
  Circle_2 circ5 = Circle_2(c5, 3, CGAL::CLOCKWISE);
  CoordNT one_minus_sqrt_3 = CoordNT(1, -1, 3);
  CoordNT one_plus_sqrt_3 = CoordNT(1, 1, 3);
  Point_2 s5 = Point_2(one_minus_sqrt_3, CoordNT(1));
  Point_2 t5 = Point_2(one_plus_sqrt_3, CoordNT(1));

  curves.push_back(Curve_2(circ5, s5, t5));

  // Create a circular arc of the unit circle, directed clockwise from
  // (-1/2, sqrt(3)/2) to (1/2, sqrt(3)/2). Note that we orient the
  // supporting circle accordingly.
  Kernel::Point_2 c6 = Kernel::Point_2(0, 0);
  CoordNT sqrt_3_div_2 = CoordNT(CGAL::Exact_rational(0),
                                 CGAL::Exact_rational(1,2),
                                 CGAL::Exact_rational(3));
  Point_2 s6 = Point_2(CGAL::Exact_rational(-1, 2), sqrt_3_div_2);
  Point_2 t6 = Point_2(CGAL::Exact_rational(1, 2), sqrt_3_div_2);

  curves.push_back(Curve_2(c6, 1, CGAL::CLOCKWISE, s6, t6));

  // Create a circular arc defined by two endpoints and a midpoint,
  // all having rational coordinates. This arc is the upper-right
  // quarter of a circle centered at the origin with radius 5.
  Kernel::Point_2 s7 = Kernel::Point_2(0, 5);
  Kernel::Point_2 mid7 = Kernel::Point_2(3, 4);
  Kernel::Point_2 t7 = Kernel::Point_2(5, 0);

  curves.push_back(Curve_2(s7, mid7, t7));

  // Construct the arrangement of the curves.
  Arrangement_2 arr;

  insert(arr, curves.begin(), curves.end());

  // Print the size of the arrangement.
  std::cout << "The arrangement size:" << std::endl
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges()
            << ",  F = " << arr.number_of_faces() << std::endl;

  return 0;
}
int main ()
{
  CGAL::set_pretty_mode(std::cout);             // for nice printouts.
  
  // Traits class object 
  AK1 ak1; 
  Traits_2 traits(&ak1);
    
  // constructor for rational functions 
  Traits_2::Construct_curve_2 construct = traits.construct_curve_2_object(); 
  
  // a polynomial representing x .-)
  Polynomial_1 x = CGAL::shift(Polynomial_1(1),1);
  
  // container storing all arcs 
  std::vector<Traits_2::Curve_2>  arcs;

  
  // Create the rational functions (y = 1 / x), and (y = -1 / x).
  Polynomial_1 P1(1);
  Polynomial_1 minusP1(-P1);
  Polynomial_1 Q1 = x;
  arcs.push_back(construct(P1, Q1));
  arcs.push_back(construct(minusP1, Q1));

  // Create a bounded segments of the parabolas (y = -4*x^2 + 3) and
  // (y = 4*x^2 - 3), defined over [-sqrt(3)/2, sqrt(3)/2].
  Polynomial_1 P2 = -4*x*x+3; 
  Polynomial_1 minusP2 = -P2; 
  std::vector<std::pair<Alg_real_1,int> > roots;

  // [-sqrt(3)/2, sqrt(3)/2]
  traits.algebraic_kernel_d_1()->solve_1_object()(P2, std::back_inserter(roots));
  arcs.push_back(construct(P2, roots[0].first, roots[1].first));
  arcs.push_back(construct(minusP2, roots[0].first, roots[1].first));

  // Create the rational function (y = 1 / 2*x) for x > 0, and the
  // rational function (y = -1 / 2*x) for x < 0.
  Polynomial_1 P3(1);
  Polynomial_1 minusP3(-P3);
  Polynomial_1 Q3 = 2*x;
  arcs.push_back(construct(P3, Q3, Alg_real_1(0), true));
  arcs.push_back(construct(minusP3, Q3, Alg_real_1(0), false));

  // Construct the arrangement of the six arcs.
  //Arrangement_2 arr(&traits);
  Arrangement_2 arr;
  insert(arr, arcs.begin(), arcs.end());

  // Print the arrangement size.
  std::cout << "The arrangement size:" << std::endl
    << "   V = " << arr.number_of_vertices()
    << " (plus " << arr.number_of_vertices_at_infinity()
    << " at infinity)"
    << ",  E = " << arr.number_of_edges() 
    << ",  F = " << arr.number_of_faces() 
    << " (" << arr.number_of_unbounded_faces() << " unbounded)"
    << std::endl << std::endl;

  return 0;
}
示例#10
0
int main ()
{
  Arrangement_2   arr;
  Point_2         ps[N_POINTS];
  Vertex_handle   vhs[N_POINTS];
  bool            valid;
  int             k;

  ps[0] = Point_2 (2, 2);
  ps[1] = Point_2 (2, 7);
  ps[2] = Point_2 (4, 9);
  ps[3] = Point_2 (4, 5);
  ps[4] = Point_2 (5, 3);
  ps[5] = Point_2 (7, 1);
  ps[6] = Point_2 (7, 5);
  ps[7] = Point_2 (7, 7);
  ps[8] = Point_2 (9, 3);
  ps[9] = Point_2 (9, 6);

  for (k = 0; k < N_POINTS; k++)
  {
    vhs[k] = insert_point (arr, ps[k]);
  }

  arr.insert_from_left_vertex (Segment_2 (Point_2 (2, 7), Point_2 (4, 7)),
                               vhs[1]);
  TEST_VALIDITY(1);

  arr.insert_from_right_vertex (Segment_2 (Point_2 (6, 6), Point_2 (7, 5)),
                                vhs[6]);
  TEST_VALIDITY(2);

  arr.insert_at_vertices (Segment_2 (Point_2 (7, 1), Point_2 (9, 3)),
                          vhs[5], vhs[8]);
  TEST_VALIDITY(3);

  arr.insert_at_vertices (Segment_2 (Point_2 (7, 5), Point_2 (9, 3)),
                          vhs[6], vhs[8]);
  TEST_VALIDITY(4);

  arr.insert_from_right_vertex (Segment_2 (Point_2 (1, 1), Point_2 (2, 7)),
                                vhs[1]);
  TEST_VALIDITY(5);

  insert_non_intersecting_curve (arr,
                                 Segment_2 (Point_2 (1, 1), Point_2 (7, 1)));
  TEST_VALIDITY(6);

  insert_non_intersecting_curve (arr,
                                 Segment_2 (Point_2 (4, 7), Point_2 (6, 6)));
  TEST_VALIDITY(7);
  
  insert_non_intersecting_curve (arr,
                                 Segment_2 (Point_2 (2, 7), Point_2 (3, 3)));
  TEST_VALIDITY(8);

  insert_non_intersecting_curve (arr,
                                 Segment_2 (Point_2 (3, 3), Point_2 (7, 1)));
  TEST_VALIDITY(9);

  arr.insert_at_vertices (Segment_2 (Point_2 (7, 5), Point_2 (9, 6)),
                          vhs[6], vhs[9]);
  TEST_VALIDITY(10);

  std::cout << "Arrangement size:"
            << "   V = " << arr.number_of_vertices()
            << " (" << arr.number_of_isolated_vertices() << " isolated)"
            << ",  E = " << arr.number_of_edges() 
            << ",  F = " << arr.number_of_faces() << std::endl;
   
  // Check the validity more thoroughly.
  valid = is_valid(arr);
  std::cout << "Arrangement is "
            << (valid ? "valid." : "NOT valid!") << std::endl;

  return (0);
}
示例#11
0
int main ()
{
  // Construct the initial arrangement.
  Arrangement_2   arr;
  Segment_2       segs[N_SEGMENTS];
  Halfedge_handle hhs[N_SEGMENTS];
  bool            valid;
  int             k;

  segs[0] = Segment_2 (Point_2 (5, 9), Point_2 (5, 11));
  segs[1] = Segment_2 (Point_2 (5, 9), Point_2 (7, 9));
  segs[2] = Segment_2 (Point_2 (5, 11), Point_2 (7, 9));
  segs[3] = Segment_2 (Point_2 (7, 6), Point_2 (9, 7));
  segs[4] = Segment_2 (Point_2 (9, 7), Point_2 (7, 9));
  segs[5] = Segment_2 (Point_2 (5, 9), Point_2 (7, 6));
  segs[6] = Segment_2 (Point_2 (10, 11), Point_2 (8, 13));
  segs[7] = Segment_2 (Point_2 (8, 13), Point_2 (11, 12));
  segs[8] = Segment_2 (Point_2 (10, 11), Point_2 (11, 12));
  segs[9] = Segment_2 (Point_2 (1, 20), Point_2 (5, 1));
  segs[10] = Segment_2 (Point_2 (5, 1), Point_2 (12, 6));
  segs[11] = Segment_2 (Point_2 (1, 20), Point_2 (12, 6));
  segs[12] = Segment_2 (Point_2 (13, 13), Point_2 (13, 15));
  segs[13] = Segment_2 (Point_2 (13, 15), Point_2 (15, 12));
  segs[14] = Segment_2 (Point_2 (13, 13), Point_2 (15, 12));
  segs[15] = Segment_2 (Point_2 (11, 12), Point_2 (13, 13));
  segs[16] = Segment_2 (Point_2 (1, 20), Point_2 (11, 17));
  segs[17] = Segment_2 (Point_2 (11, 17), Point_2 (20, 13));
  segs[18] = Segment_2 (Point_2 (12, 6), Point_2 (20, 13));
  segs[19] = Segment_2 (Point_2 (15, 12), Point_2 (20, 13));
  segs[20] = Segment_2 (Point_2 (5, 1), Point_2 (20, 1));
  segs[21] = Segment_2 (Point_2 (20, 1), Point_2 (20, 13));
  segs[22] = Segment_2 (Point_2 (15, 5), Point_2 (17, 3));
  segs[23] = Segment_2 (Point_2 (13, 3), Point_2 (17, 3));
  segs[24] = Segment_2 (Point_2 (12, 6), Point_2 (13, 3));
  segs[25] = Segment_2 (Point_2 (17, 3), Point_2 (20, 1));
  
  for (k = 0; k < N_SEGMENTS; k++)
  {
    hhs[k] = insert_non_intersecting_curve (arr, segs[k]);
  }
  valid = arr.is_valid();

  std::cout << "Arrangement size:"
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges() 
            << ",  F = " << arr.number_of_faces() << std::endl;
  std::cout << "The arrangement is "
            << (valid ? "valid." : "NOT valid!") << std::endl;
 
  if (! valid)
    return (1);

  // Remove some edges.
  int  del_indices[N_REMOVE] = {25, 23, 22, 1, 3, 11, 19, 15, 4, 24};

  for (k = 0; k < N_REMOVE; k++)
  {
    arr.remove_edge (hhs[del_indices[k]]);
    valid = arr.is_valid();
    std::cout << "  Removed " << k+1 << " segment(s), arrangement is "
              << (valid ? "valid." : "NOT valid!") << std::endl;

    if (! valid)
      return (1);
  }

  std::cout << "Final arrangement size:"
            << "   V = " << arr.number_of_vertices()
            << ",  E = " << arr.number_of_edges() 
            << ",  F = " << arr.number_of_faces() << std::endl;

  // Check the validity more thoroughly.
  valid = is_valid(arr);
  std::cout << "Arrangement is "
              << (valid ? "valid." : "NOT valid!") << std::endl;
 
  return (0);
}