mirror of https://github.com/CGAL/cgal
464 lines
17 KiB
C
464 lines
17 KiB
C
// ======================================================================
|
|
//
|
|
// Copyright (c) 1999 The GALIA Consortium
|
|
//
|
|
// This software and related documentation is part of the
|
|
// Computational Geometry Algorithms Library (CGAL).
|
|
//
|
|
// Every use of CGAL requires a license. Licenses come in three kinds:
|
|
//
|
|
// - For academic research and teaching purposes, permission to use and
|
|
// copy the software and its documentation is hereby granted free of
|
|
// charge, provided that
|
|
// (1) it is not a component of a commercial product, and
|
|
// (2) this notice appears in all copies of the software and
|
|
// related documentation.
|
|
// - Development licenses grant access to the source code of the library
|
|
// to develop programs. These programs may be sold to other parties as
|
|
// executable code. To obtain a development license, please contact
|
|
// the GALIA Consortium (at cgal@cs.uu.nl).
|
|
// - Commercialization licenses grant access to the source code and the
|
|
// right to sell development licenses. To obtain a commercialization
|
|
// license, please contact the GALIA Consortium (at cgal@cs.uu.nl).
|
|
//
|
|
// This software and documentation is provided "as-is" and without
|
|
// warranty of any kind. In no event shall the CGAL Consortium be
|
|
// liable for any damage of any kind.
|
|
//
|
|
// The GALIA Consortium consists of Utrecht University (The Netherlands),
|
|
// ETH Zurich (Switzerland), Free University of Berlin (Germany),
|
|
// INRIA Sophia-Antipolis (France), Trier University
|
|
// (Germany), Max-Planck-Institute Saarbrucken (Germany),
|
|
// and Tel-Aviv University (Israel).
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// file : demo/GeoWin/CGAL_arrangement_2.C
|
|
//
|
|
// ======================================================================
|
|
|
|
/*
|
|
|
|
Ideen:
|
|
- point location einstellbar machen !
|
|
- Nutzerinteraktion einstellbar
|
|
- counter einblenden
|
|
- Farben
|
|
|
|
*/
|
|
|
|
//#define DEBUG
|
|
#define CGAL_PROVIDE_LEDA_RAT_KERNEL_TRAITS_3
|
|
#define CGAL_NO_DEPRECATED_CODE
|
|
#include <CGAL/basic.h>
|
|
|
|
#if !defined(CGAL_USE_LEDA) || (__LEDA__ < 400)
|
|
#include <iostream>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
std::cout << "No LEDA 4.0 or higher installed!\n";
|
|
std::cout << "A LEDA version >= 4.0 is required to run GeoWin!\n";
|
|
return 0;
|
|
}
|
|
#else
|
|
|
|
#include <CGAL/Cartesian.h>
|
|
#include <CGAL/Kernel_special.h>
|
|
#include <CGAL/kernel_event_support.h>
|
|
#include <CEP/Leda_rat_kernel/leda_rat_kernel_traits.h>
|
|
#include <CEP/Leda_rat_kernel/geowin_leda_rat_kernel.h>
|
|
#include <CGAL/Arrangement_2.h>
|
|
#include <CGAL/Arr_2_default_dcel.h>
|
|
#include <CGAL/Arr_segment_traits_2.h>
|
|
#include <CGAL/geowin_support.h>
|
|
|
|
#if defined(LEDA_NAMESPACE)
|
|
using namespace leda;
|
|
#endif
|
|
|
|
|
|
typedef CGAL::leda_rat_kernel_traits LEDA_KERNEL;
|
|
typedef CGAL::kernel_event<LEDA_KERNEL> KEV;
|
|
typedef CGAL::kernel_event<int> KRES;
|
|
typedef CGAL::Kernel_special<LEDA_KERNEL, KEV, KRES> K;
|
|
|
|
typedef CGAL::Arr_segment_traits_2<K> Traits;
|
|
|
|
typedef K::Point_2 IPoint;
|
|
typedef K::Point_2 Point;
|
|
typedef K::Segment_2 Segment;
|
|
typedef Traits::X_curve X_curve;
|
|
|
|
typedef CGAL::Arr_base_node<X_curve> Base_node;
|
|
typedef CGAL::Arr_2_default_dcel<Traits> Dcel;
|
|
typedef CGAL::Arrangement_2<Dcel,Traits,Base_node > Arr_2;
|
|
|
|
typedef CGAL::Arrangement_2<Dcel,Traits,Base_node >::Curve_iterator Curve_iterator;
|
|
typedef CGAL::Arrangement_2<Dcel,Traits,Base_node >::Vertex_iterator Vertex_iterator;
|
|
typedef CGAL::Arrangement_2<Dcel,Traits,Base_node >::Vertex Vertex;
|
|
|
|
// functors of the adapted kernel ...
|
|
typedef LEDA_KERNEL::Is_vertical_2 Is_vertical_2;
|
|
typedef LEDA_KERNEL::Construct_vertex_2 Construct_vertex_2;
|
|
typedef LEDA_KERNEL::Less_x_2 Less_x_2;
|
|
typedef LEDA_KERNEL::Construct_segment_2 Construct_segment_2;
|
|
typedef LEDA_KERNEL::Compare_xy_2 Compare_xy_2;
|
|
|
|
typedef LEDA_KERNEL::Compare_x_2 Compare_x_2;
|
|
typedef LEDA_KERNEL::Compare_y_2 Compare_y_2;
|
|
typedef LEDA_KERNEL::Less_y_2 Less_y_2;
|
|
typedef LEDA_KERNEL::Equal_2 Equal_2;
|
|
typedef LEDA_KERNEL::Compare_y_at_x_2 Compare_y_at_x_2;
|
|
typedef LEDA_KERNEL::Compare_slope_2 Compare_slope_2;
|
|
typedef LEDA_KERNEL::Counterclockwise_in_between_2 Counterclockwise_in_between_2;
|
|
typedef LEDA_KERNEL::Construct_direction_2 Construct_direction_2;
|
|
typedef LEDA_KERNEL::Construct_opposite_direction_2 Construct_opposite_direction_2;
|
|
|
|
|
|
|
|
Arr_2 arr;
|
|
bool graphical_output = false;
|
|
|
|
class geo_locate : public geowin_update<std::list<Point>,std::list<Segment> >
|
|
{
|
|
public:
|
|
|
|
int is_vertical_counter;
|
|
int construct_vertex_counter;
|
|
int less_x_counter;
|
|
int construct_segment_counter;
|
|
int compare_xy_counter;
|
|
|
|
CGAL::event_item Is_vertical_2_it;
|
|
CGAL::event_item Construct_vertex_2_it;
|
|
CGAL::event_item Less_x_2_it;
|
|
CGAL::event_item Construct_segment_2_it;
|
|
CGAL::event_item Compare_xy_2_it;
|
|
|
|
// check some others ...
|
|
CGAL::event_item Compare_x_2_it;
|
|
CGAL::event_item Compare_y_2_it;
|
|
CGAL::event_item Less_y_2_it;
|
|
CGAL::event_item Equal_2_point_it;
|
|
CGAL::event_item Equal_2_segment_it;
|
|
CGAL::event_item Compare_y_at_x_2_point_segment_segment_it;
|
|
CGAL::event_item Compare_y_at_x_2_point_segment_it;
|
|
CGAL::event_item Compare_slope_2_it;
|
|
CGAL::event_item Counterclockwise_in_between_2_it;
|
|
CGAL::event_item Construct_direction_2_it;
|
|
CGAL::event_item Construct_opposite_direction_2_it;
|
|
|
|
int equal_2_op_point;
|
|
int equal_2_op_segment;
|
|
int compare_x_2_op;
|
|
int compare_y_2_op;
|
|
int less_y_2_op;
|
|
int compare_y_at_x_2_op_point_segment_segment;
|
|
int compare_y_at_x_2_op_point_segment;
|
|
int compare_slope_2_op;
|
|
int counterclockwise_in_between_2_op;
|
|
int construct_direction_2_op;
|
|
int construct_opposite_direction_2_op;
|
|
|
|
Point loc_point;
|
|
GeoWin& gw;
|
|
leda_window& win;
|
|
|
|
geo_locate(GeoWin& g) : gw(g), win(g.get_window())
|
|
{ }
|
|
|
|
// ---------------------------------------------------------------------------------------------------------
|
|
// other stuff
|
|
// ---------------------------------------------------------------------------------------------------------
|
|
|
|
void equal_2_op_point_counter(const LEDA_KERNEL::Equal_2&, const Point& p1, const Point& p2)
|
|
{ equal_2_op_point++; }
|
|
void equal_2_op_segment_counter(const LEDA_KERNEL::Equal_2&, const Segment& s1, const Segment& s2)
|
|
{ equal_2_op_segment++; }
|
|
void compare_x_2_op_counter(const LEDA_KERNEL::Compare_x_2&, const Point& p1, const Point& p2)
|
|
{ compare_x_2_op++; }
|
|
void compare_y_2_op_counter(const LEDA_KERNEL::Compare_y_2&, const Point& p1, const Point& p2)
|
|
{ compare_y_2_op++; }
|
|
void less_y_2_op_counter(const LEDA_KERNEL::Less_y_2&, const Point& p1, const Point& p2)
|
|
{ less_y_2_op++; }
|
|
void compare_y_at_x_2_op_point_segment_segment_counter(const LEDA_KERNEL::Compare_y_at_x_2&, const Point& p, const Point& s1,
|
|
const Segment& s2)
|
|
{ compare_y_at_x_2_op_point_segment_segment++; }
|
|
void compare_y_at_x_2_op_point_segment_counter(const LEDA_KERNEL::Compare_y_at_x_2&, const Point& p, const Segment& s1)
|
|
{ compare_y_at_x_2_op_point_segment++; }
|
|
|
|
void compare_slope_2_op_counter(const LEDA_KERNEL::Compare_slope_2&,const Segment& s1, const Segment& s2)
|
|
{ compare_slope_2_op++; }
|
|
|
|
void counterclockwise_in_between_2_op_counter(const LEDA_KERNEL::Counterclockwise_in_between_2&,
|
|
const leda::rat_direction & d,
|
|
const leda::rat_direction & d1,
|
|
const leda::rat_direction & d2)
|
|
{ counterclockwise_in_between_2_op++; }
|
|
void construct_direction_2_op_counter(const LEDA_KERNEL::Construct_direction_2&, const Segment& s)
|
|
{ construct_direction_2_op++; }
|
|
void construct_opposite_direction_2_op_counter(const LEDA_KERNEL::Construct_opposite_direction_2&, const leda::rat_direction & d)
|
|
{ construct_opposite_direction_2_op++; }
|
|
|
|
// ---------------------------------------------------------------------------------------------------------
|
|
|
|
void is_vertical_occurence(const LEDA_KERNEL::Is_vertical_2&, const Segment& obj)
|
|
{ std::cout << "is_vertical:" << obj << "\n";
|
|
is_vertical_counter++;
|
|
}
|
|
|
|
void construct_vertex_occurence(const LEDA_KERNEL::Construct_vertex_2&, const Segment& obj, const int& i)
|
|
{ std::cout << "construct_vertex:" << obj << " " << i << "\n";
|
|
construct_vertex_counter++;
|
|
}
|
|
|
|
void less_x_occurence(const LEDA_KERNEL::Less_x_2&, const Point& p1, const Point& p2, const bool&)
|
|
{ std::cout << "less_x_2:" << p1 << " " << p2 << "\n";
|
|
less_x_counter++;
|
|
|
|
if (graphical_output){
|
|
Point other;
|
|
other = leda::identical(p1,loc_point) ? p2 : p1;
|
|
win.draw_arrow(loc_point.to_float(), other.to_float(), blue);
|
|
leda_wait(0.5);
|
|
}
|
|
}
|
|
|
|
void construct_segment_occurence(const LEDA_KERNEL::Construct_segment_2&, const Point& p1, const Point& p2)
|
|
{ std::cout << "construct_segment:" << p1 << " " << p2 << "\n";
|
|
construct_segment_counter++;
|
|
}
|
|
|
|
void compare_xy_occurence(const LEDA_KERNEL::Compare_xy_2&, const Point& p1, const Point& p2)
|
|
{ std::cout << "compare_xy_2:" << p1 << " " << p2 << "\n";
|
|
compare_xy_counter++;
|
|
}
|
|
|
|
/*
|
|
Problem: nur das eine Resultevent geht - warum ???
|
|
*/
|
|
|
|
void init_visualization(const Point& locate)
|
|
{
|
|
loc_point = locate;
|
|
|
|
// set counters ...
|
|
std::cout << "\n\n";
|
|
is_vertical_counter = 0;
|
|
construct_vertex_counter = 0;
|
|
less_x_counter = 0;
|
|
construct_segment_counter = 0;
|
|
compare_xy_counter = 0;
|
|
|
|
// others ...
|
|
equal_2_op_point = 0;
|
|
equal_2_op_segment = 0;
|
|
compare_x_2_op = 0;
|
|
compare_y_2_op = 0;
|
|
less_y_2_op = 0;
|
|
compare_y_at_x_2_op_point_segment_segment = 0;
|
|
compare_y_at_x_2_op_point_segment = 0;
|
|
compare_slope_2_op = 0;
|
|
counterclockwise_in_between_2_op = 0;
|
|
construct_direction_2_op = 0;
|
|
construct_opposite_direction_2_op = 0;
|
|
|
|
Is_vertical_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::is_vertical_occurence);
|
|
Construct_vertex_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::construct_vertex_occurence);
|
|
Less_x_2_it = CGAL::attach(KRES::EVENT, *this, &geo_locate::less_x_occurence);
|
|
Construct_segment_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::construct_segment_occurence);
|
|
Compare_xy_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_xy_occurence);
|
|
|
|
Compare_x_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_x_2_op_counter);
|
|
Compare_y_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_y_2_op_counter);
|
|
Less_y_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::less_y_2_op_counter);
|
|
Equal_2_point_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::equal_2_op_point_counter);
|
|
Equal_2_segment_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::equal_2_op_segment_counter);
|
|
Compare_y_at_x_2_point_segment_segment_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_y_at_x_2_op_point_segment_segment_counter);
|
|
Compare_y_at_x_2_point_segment_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_y_at_x_2_op_point_segment_counter);
|
|
Compare_slope_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::compare_slope_2_op_counter);
|
|
Counterclockwise_in_between_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::counterclockwise_in_between_2_op_counter);
|
|
Construct_direction_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::construct_direction_2_op_counter);
|
|
Construct_opposite_direction_2_it = CGAL::attach(KEV::EVENT, *this, &geo_locate::construct_opposite_direction_2_op_counter);
|
|
}
|
|
|
|
void reset_visualization() {
|
|
// output counters ...
|
|
std::cout << "\ncounters:\n";
|
|
std::cout << "---------------\n";
|
|
std::cout << "is_vertical_counter:" << is_vertical_counter << "\n";
|
|
std::cout << "construct_vertex_counter:" << construct_vertex_counter << "\n";
|
|
std::cout << "less_x_counter:" << less_x_counter << "\n";
|
|
std::cout << "construct_segment_counter:" << construct_segment_counter << "\n";
|
|
std::cout << "compare_xy_counter:" << compare_xy_counter << "\n";
|
|
std::cout << "\nother counters:\n";
|
|
std::cout << "---------------\n";
|
|
std::cout << "point equality:" << equal_2_op_point << "\n";
|
|
std::cout << "segment equality:" << equal_2_op_segment << "\n";
|
|
std::cout << "point compare x:" << compare_x_2_op << "\n";
|
|
std::cout << "point compare y:" << compare_y_2_op << "\n";
|
|
std::cout << "point less y:" << less_y_2_op << "\n";
|
|
std::cout << "compare_y_at_x_2 (point/segment/segment):" << compare_y_at_x_2_op_point_segment_segment << "\n";
|
|
std::cout << "compare_y_at_x_2 (point/segment):" << compare_y_at_x_2_op_point_segment << "\n";
|
|
std::cout << "compare_slope:" << compare_slope_2_op << "\n";
|
|
std::cout << "counterclockwise_in_between:" << counterclockwise_in_between_2_op << "\n";
|
|
std::cout << "construct_direction:" << construct_direction_2_op << "\n";
|
|
std::cout << "construct_opposite_direction:" << construct_opposite_direction_2_op << "\n";
|
|
std::cout << "\n\n";
|
|
|
|
gw.msg_open(leda::string("construct_vertex_counter:%d",construct_vertex_counter));
|
|
gw.msg_open(leda::string("less_x_counter:%d",less_x_counter));
|
|
|
|
CGAL::detach(Is_vertical_2_it);
|
|
CGAL::detach(Construct_vertex_2_it);
|
|
CGAL::detach(Less_x_2_it);
|
|
CGAL::detach(Construct_segment_2_it);
|
|
CGAL::detach(Compare_xy_2_it);
|
|
|
|
// others ...
|
|
CGAL::detach(Compare_x_2_it);
|
|
CGAL::detach(Compare_y_2_it);
|
|
CGAL::detach(Less_y_2_it);
|
|
CGAL::detach(Equal_2_point_it);
|
|
CGAL::detach(Equal_2_segment_it);
|
|
CGAL::detach(Compare_y_at_x_2_point_segment_segment_it);
|
|
CGAL::detach(Compare_y_at_x_2_point_segment_it);
|
|
CGAL::detach(Compare_slope_2_it);
|
|
CGAL::detach(Counterclockwise_in_between_2_it);
|
|
CGAL::detach(Construct_direction_2_it);
|
|
CGAL::detach(Construct_opposite_direction_2_it);
|
|
}
|
|
|
|
void update(const std::list<Point>& LP, std::list<Segment>& Sl)
|
|
{
|
|
Sl.clear();
|
|
|
|
// empty ?
|
|
Curve_iterator cit = arr.curve_node_begin();
|
|
|
|
if (cit==arr.curve_node_end()) return; //empty
|
|
|
|
// perform locate operations (and compute output)...
|
|
Arr_2::Locate_type lt;
|
|
Arr_2::Halfedge_handle e;
|
|
|
|
std::list<Point>::const_iterator pit= LP.begin();
|
|
|
|
for(;pit != LP.end(); ++pit){
|
|
Point pt = *pit;
|
|
|
|
// switch events on ...
|
|
init_visualization(pt);
|
|
e = arr.locate(pt,lt);
|
|
reset_visualization();
|
|
// ... and off
|
|
|
|
//color the face on the screen
|
|
Arr_2::Face_handle f=e->face();
|
|
if (f->does_outer_ccb_exist()) {
|
|
Arr_2::Ccb_halfedge_circulator cc=f->outer_ccb();
|
|
do {
|
|
Segment seg = cc->curve();
|
|
Sl.push_back(seg);
|
|
} while (++cc != f->outer_ccb());
|
|
|
|
}
|
|
|
|
Arr_2::Holes_iterator hit=f->holes_begin(),eit=f->holes_end();
|
|
for (;hit!=eit; ++hit) {
|
|
Arr_2::Ccb_halfedge_circulator cc=*hit;
|
|
do {
|
|
Segment seg = cc->curve();
|
|
Sl.push_back(seg);
|
|
} while (++cc != *hit);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
class geo_seg_arr : public geowin_update<std::list<Segment>,std::list<Segment> >,
|
|
public geowin_redraw
|
|
{
|
|
public:
|
|
|
|
bool insert(const Segment& seg)
|
|
{
|
|
arr.insert(X_curve(seg));
|
|
return true;
|
|
}
|
|
|
|
void draw(leda_window& W, leda_color c1, leda_color c2,double x1,double y1,double x2,double y2)
|
|
{ leda_color cold = W.set_color(c1);
|
|
// draw vertices of arrangement
|
|
Vertex_iterator vit = arr.vertices_begin();
|
|
|
|
for(;vit != arr.vertices_end();vit++){
|
|
Vertex vpm = *vit;
|
|
W << vpm.point();
|
|
}
|
|
|
|
W.set_color(cold);
|
|
}
|
|
|
|
void update(const std::list<Segment>& L, std::list<Segment>& Sl)
|
|
{
|
|
// clear Arrangement
|
|
arr.clear();
|
|
|
|
// insert segments ...
|
|
std::list<Segment>::const_iterator it1= L.begin();
|
|
|
|
for(;it1 != L.end(); ++it1){
|
|
const Segment& s1= *it1;
|
|
arr.insert(X_curve(s1));
|
|
}
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
geowin_init_default_type((std::list<Segment>*)0, leda_string("CGALSegmentList"));
|
|
geowin_init_default_type((std::list<Point>*)0, leda_string("CGALPointList"));
|
|
|
|
std::list<Segment> L;
|
|
std::list<Point> LP;
|
|
|
|
GeoWin GW("CGAL - Segment Arrangements and locate operations");
|
|
|
|
geo_scene seg_scene = GW.new_scene(L);
|
|
GW.set_name(seg_scene,"Input for line segment arrangement");
|
|
GW.set_color( seg_scene, leda_green );
|
|
GW.set_line_width( seg_scene, 3 );
|
|
GW.set_active_line_width( seg_scene, 3 );
|
|
|
|
geo_scene loc_input = GW.new_scene(LP);
|
|
GW.set_name(loc_input, "Input for point location");
|
|
GW.set_point_style(loc_input, leda_disc_point);
|
|
|
|
geo_seg_arr arr;
|
|
//geo_scene res =
|
|
GW.new_scene(arr,arr,seg_scene,leda_string("Segment arrangement"));
|
|
|
|
geo_locate locate(GW);
|
|
geo_scene loc = GW.new_scene(locate,loc_input,leda_string("Arrangement locate operations"));
|
|
GW.set_color( loc, leda_red );
|
|
GW.set_line_width( loc, 3 );
|
|
GW.set_fill_color( loc, leda_red);
|
|
|
|
GW.add_dependence(seg_scene,loc);
|
|
|
|
GW.set_all_visible(true);
|
|
|
|
GW.message("To perform point locations, activate in the Scenes menu the input scene for point location.");
|
|
|
|
GW.init_menu();
|
|
GW.get_window().bool_item(" Output in algorithm:",graphical_output);
|
|
GW.edit(seg_scene);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|