Gtk2-Ex-Geo-Graph
view release on metacpan or search on metacpan
lib/Gtk2/Ex/Geo/Graph.pm view on Meta::CPAN
$miny = min($miny, $v->{point}->{Y});
$maxx = max($maxx, $v->{point}->{X});
$maxy = max($maxy, $v->{point}->{Y});
}
}
return ($minx, $miny, $maxx, $maxy) if defined $minx;
return ();
}
sub render {
my($self, $pb, $cr, $overlay, $viewport) = @_;
my @s = @{$self->selected_features()};
my %selected = map { (ref($_) eq 'HASH' ? $_ : $_->[0].$_->[1] ) => 1 } @s;
my $a = $self->alpha/255.0;
my @color = $self->single_color;
for (@color) {
$_ /= 255.0;
$_ *= $a;
}
$cr->set_line_width(1);
$cr->set_source_rgba(@color);
for my $v ($self->{graph}->vertices) {
my @p = $overlay->point2surface($v->{point}->{X}, $v->{point}->{Y});
for (@p) {
$_ = bounds($_, -10000, 10000);
}
$cr->arc(@p, $NODE_RAY, 0, 2*3.1415927);
$cr->fill_preserve if $selected{$v};
$cr->stroke;
}
for my $e ($self->{graph}->edges) {
my($u, $v) = @$e;
my @p = $overlay->point2surface($u->{point}->{X}, $u->{point}->{Y});
my @q = $overlay->point2surface($v->{point}->{X}, $v->{point}->{Y});
for (@p, @q) {
$_ = bounds($_, -10000, 10000);
}
$cr->move_to(@p);
$cr->line_to(@q);
$cr->set_line_width(3) if $selected{$u.$v};
$cr->stroke;
$cr->set_line_width(1) if $selected{$u.$v};
}
lib/Gtk2/Ex/Geo/Graph.pm view on Meta::CPAN
sub nodes_selected {
my($selection) = @_;
my($self, $gui) = @{pop()};
return if $self->{ignore_cursor_change};
my $selected = get_selected_from_selection($selection);
$self->select();
for my $v ($self->{graph}->vertices) {
push @{$self->selected_features}, $v if $selected->{$v->{index}};
}
$gui->{overlay}->render;
}
sub open_links_dialog {
my($self, $gui) = @{pop()};
my $dialog = Gtk2::Dialog->new('Nodes of '.$self->name, undef, [], 'gtk-close' => 'close');
$dialog->set_default_size(600, 500);
$dialog->set_transient_for(undef);
$dialog->signal_connect(response => sub { $_[0]->destroy });
$dialog->show_all;
}
sub bounds {
$_[0] < $_[1] ? $_[1] : ($_[0] > $_[2] ? $_[2] : $_[0]);
}
sub got_focus {
my($self, $gui) = @_;
my $o = $gui->{overlay};
$self->{_tag1} = $o->signal_connect(
drawing_changed => \&drawing_changed, [$self, $gui]);
$self->{_tag2} = $o->signal_connect(
new_selection => \&new_selection, [$self, $gui]);
$self->{_tag3} = $o->signal_connect(
key_press_event => \&key_pressed, [$self, $gui]);
$gui->set_interaction_mode('Draw');
$gui->set_interaction_geometry('Line');
$o->{show_selection} = 0;
}
sub lost_focus {
my($self, $gui) = @_;
for (qw/_tag1 _tag2 _tag3/) {
$gui->{overlay}->signal_handler_disconnect($self->{$_}) if $self->{$_};
delete $self->{$_};
}
}
sub drawing_changed {
my($self, $gui) = @{$_[1]};
my $drawing = $gui->{overlay}->{drawing};
if ($drawing->isa('Geo::OGC::LineString') and $drawing->NumPoints == 2) {
my $v1 = $self->find_vertex($gui, $drawing->StartPoint);
my $v2 = $self->find_vertex($gui, $drawing->EndPoint);
unless ($v1) {
$v1 = { point => $drawing->StartPoint->Clone };
$v1->{index} = $self->{index}++;
$self->{graph}->add_vertex($v1);
}
unless ($v2) {
$v2 = { point => $drawing->EndPoint->Clone };
$v2->{index} = $self->{index}++;
$self->{graph}->add_vertex($v2);
}
my $w = $drawing->Length;
$self->{graph}->add_weighted_edge($v1, $v2, $w);
}
delete $gui->{overlay}->{drawing};
$gui->{overlay}->render;
}
sub find_vertex {
my($self, $gui, $point) = @_;
my $d = -1;
my $c;
for my $v ($self->{graph}->vertices) {
my $e = $point->Distance($v->{point});
($c, $d) = ($v, $e) if $d < 0 or $e < $d;
}
return $c if $d/$gui->{overlay}->{pixel_size} < $NODE_RAY;
}
sub find_edge {
my($self, $gui, $point) = @_;
my $d = -1;
my $c;
for my $e ($self->{graph}->edges) {
my $e2 = Geo::OGC::LineString->new;
$e2->AddPoint($e->[0]->{point});
$e2->AddPoint($e->[1]->{point});
my $d2 = $point->Distance($e2);
($c, $d) = ($e, $d2) if $d < 0 or $d2 < $d;
}
return $c if $d/$gui->{overlay}->{pixel_size} < $NODE_RAY;
}
sub new_selection {
my($self, $gui) = @{$_[1]};
my $selection = $gui->{overlay}->{selection};
$self->select();
$self->_select($gui, $selection);
if ($self->{nodes_dialog}) {
my $view = $self->{nodes_view};
my $model = $view->get_model;
my $selection = $view->get_selection;
$self->{ignore_cursor_change} = 1;
$selection->unselect_all;
for my $v (@{$self->selected_features}) {
next if ref($v) eq 'ARRAY';
$model->foreach( \&select_in_selection, [$selection, $v->{index}]);
}
delete $self->{ignore_cursor_change};
}
$gui->{overlay}->render;
}
sub select_in_selection {
my($selection, $index) = @{pop()};
my($model, $path, $iter) = @_;
my($x) = $model->get($iter);
if ($x == $index) {
$selection->select_iter($iter);
return 1;
}
lib/Gtk2/Ex/Geo/Graph.pm view on Meta::CPAN
my $v = $self->find_vertex($gui, $selection);
push @{$self->selected_features}, $v if $v;
unless ($v) {
my $e = $self->find_edge($gui, $selection);
push @{$self->selected_features}, $e if $e;
}
}
}
sub key_pressed {
my($overlay, $event, $user) = @_;
my $key = $event->keyval;
return unless $key == $Gtk2::Gdk::Keysyms{Delete};
my($self, $gui) = @{$user};
my @v;
my @e;
for my $v (@{$self->selected_features()}) {
if (ref $v eq 'HASH') {
push @v, $v;
} else {
push @e, ($v->[0], $v->[1]);
}
}
$self->{graph}->delete_vertices(@v);
$self->{graph}->delete_edges(@e);
$self->select();
$gui->{overlay}->render;
}
sub open_properties_dialog {
my($self, $gui) = @_;
}
sub shortest_path {
my($self) = @_;
my($u, $v);
for my $x (@{$self->selected_features()}) {
lib/Gtk2/Ex/Geo/Graph.pm view on Meta::CPAN
$u = $x,next unless $u;
$v = $x unless $v;
last;
}
$self->select();
return unless $u and $v;
print STDERR "sp $u->$v\n";
my @path = $self->{graph}->SP_Dijkstra($u, $v);
print STDERR "sp @path\n";
$self->selected_features(\@path);
#$gui->{overlay}->render;
}
## @ignore
sub min {
$_[0] > $_[1] ? $_[1] : $_[0];
}
## @ignore
sub max {
$_[0] > $_[1] ? $_[0] : $_[1];
use Gtk2::Ex::Geo;
BEGIN {
use_ok('Gtk2::Ex::Geo::Graph');
};
Gtk2->init;
my($window, $gis) = setup (classes => [qw/Gtk2::Ex::Geo::Layer Gtk2::Ex::Geo::Graph/]);
$gis->{overlay}->signal_connect(update_layers =>
sub {
#print STDERR "in callback: @_\n";
});
exit unless $ENV{GUI};
Gtk2->main;
sub setup{
my %params = @_;
}
# layer list
my $list = Gtk2::ScrolledWindow->new();
$list->set_policy("never", "automatic");
$list->add($gis->{tree_view});
# layer list and the map
my $hbox = Gtk2::HBox->new(FALSE, 0);
$hbox->pack_start($list, FALSE, FALSE, 0);
$hbox->pack_start($gis->{overlay}, TRUE, TRUE, 0);
# the stack
my $vbox = Gtk2::VBox->new(FALSE, 0);
$vbox->pack_start($gis->{toolbar}, FALSE, FALSE, 0);
#$vbox->add($hbox);
$vbox->pack_start($hbox, TRUE, TRUE, 0);
$vbox->pack_start($gis->{entry}, FALSE, FALSE, 0);
$vbox->pack_start($gis->{statusbar}, FALSE, FALSE, 0);
$window->add($vbox);
( run in 0.380 second using v1.01-cache-2.11-cpan-cba739cd03b )