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; }
int main () { // Construct the arrangement containing two intersecting triangles. Arrangement_2 arr; Face_index_observer obs (arr); Segment_2 s1 (Point_2(4, 1), Point_2(7, 6)); Segment_2 s2 (Point_2(1, 6), Point_2(7, 6)); Segment_2 s3 (Point_2(4, 1), Point_2(1, 6)); Segment_2 s4 (Point_2(1, 3), Point_2(7, 3)); Segment_2 s5 (Point_2(1, 3), Point_2(4, 8)); Segment_2 s6 (Point_2(4, 8), Point_2(7, 3)); insert_non_intersecting_curve (arr, s1); insert_non_intersecting_curve (arr, s2); insert_non_intersecting_curve (arr, s3); insert (arr, s4); insert (arr, s5); insert (arr, s6); // Go over all arrangement faces and print the index of each face and it // outer boundary. The face index is stored in its data field in our case. Arrangement_2::Face_const_iterator fit; Arrangement_2::Ccb_halfedge_const_circulator curr; std::cout << arr.number_of_faces() << " faces:" << std::endl; for (fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) { std::cout << "Face no. " << fit->data() << ": "; if (fit->is_unbounded()) std::cout << "Unbounded." << std::endl; else { curr = fit->outer_ccb(); std::cout << curr->source()->point(); do { std::cout << " --> " << curr->target()->point(); ++curr; } while (curr != fit->outer_ccb()); std::cout << std::endl; } } return 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; }
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; }
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; }
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); }
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); }