|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Geo::ShapeFile::Shape;  | 
| 
2
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
14
 | 
 use strict;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
    | 
| 
3
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
10
 | 
 use warnings;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
    | 
| 
4
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
10
 | 
 use Carp;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
100
 | 
    | 
| 
5
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
987
 | 
 use Tree::R;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11099
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
101
 | 
    | 
| 
6
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
20
 | 
 use List::Util qw /min max/;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
229
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
14
 | 
 use Geo::ShapeFile;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
    | 
| 
9
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
918
 | 
 use Geo::ShapeFile::Point;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
10
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
958
 | 
 use Geo::ShapeFile::Shape::Index;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
75
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
12
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
912
 | 
 use parent qw /Geo::ShapeFile/;  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
600
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '3.03';  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $little_endian_sys = unpack 'b', (pack 'S', 1 );  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $index_class = 'Geo::ShapeFile::Shape::Index';  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
21
 | 
7416
 | 
 
 | 
 
 | 
  
7416
  
 | 
  
1
  
 | 
11910
 | 
     my $proto = shift;  | 
| 
22
 | 
7416
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
24646
 | 
     my $class = ref ($proto) || $proto;  | 
| 
23
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14972
 | 
     my %args  = @_;  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
25
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
89851
 | 
     my $self = {  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_content_length  => 0,  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         source              => undef,  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_points          => [],  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_num_points      => 0,  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_parts           => [],  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_record_number   => undef,  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_shape_type      => undef,  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_num_parts       => 0,  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_x_min           => undef,  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_x_max           => undef,  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_y_min           => undef,  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_y_max           => undef,  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_z_min           => undef,  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_z_max           => undef,  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_m_min           => undef,  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_m_max           => undef,  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         shp_data            => undef,  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
45
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23483
 | 
     foreach (keys %args) {  | 
| 
46
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{$_} = $args{$_};  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
49
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12769
 | 
     bless $self, $class;  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
51
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18777
 | 
     return $self;  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse_shp {  | 
| 
55
 | 
7416
 | 
 
 | 
 
 | 
  
7416
  
 | 
  
0
  
 | 
10799
 | 
     my $self = shift;  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14252
 | 
     $self->{source} = $self->{shp_data} = shift;  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
59
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18201
 | 
     $self->_extract_ints('big', 'shp_record_number', 'shp_content_length');  | 
| 
60
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17401
 | 
     $self->_extract_ints('little', 'shp_shape_type');  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
62
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19959
 | 
     my $parser = '_parse_shp_' . $self->type($self->{shp_shape_type});  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
64
 | 
7416
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29658
 | 
     croak "Can't parse shape_type $self->{shp_shape_type}"  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if !$self->can($parser);  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
67
 | 
7416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20189
 | 
     $self->$parser();  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
69
 | 
7416
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23029
 | 
     if (length($self->{shp_data})) {  | 
| 
70
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $len = length($self->{shp_data});  | 
| 
71
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $byte_plural = $len > 1 ? 's' : '';  | 
| 
72
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         carp "$len byte$byte_plural remaining in buffer after parsing "  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         . $self->shape_type_text()  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         . ' #'  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         . $self->shape_id();  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_Null {  | 
| 
80
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # TODO - document this  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add_point {  | 
| 
85
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $self = shift;  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
87
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if(@_ == 1) {  | 
| 
88
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $point = shift;  | 
| 
89
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if($point->isa('Geo::ShapeFile::Point')) {  | 
| 
90
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             push @{$self->{shp_points}}, $point;  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
94
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my %point_opts = @_;  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push @{$self->{shp_points}}, Geo::ShapeFile::Point->new(%point_opts);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
97
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{shp_num_points}++;  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # TODO - document this  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add_part {  | 
| 
103
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $self = shift;  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @{$self->{shp_parts}}, $self->{shp_num_parts}++;  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # TODO - finish me  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub calculate_bounds {  | 
| 
110
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $self = shift;  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
112
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my %bounds = $self->find_bounds($self->points);  | 
| 
113
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach (keys %bounds) {  | 
| 
114
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'shp_' . $_} = $bounds{$_};  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
116
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return %bounds;  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_Point {  | 
| 
120
 | 
2553
 | 
 
 | 
 
 | 
  
2553
  
 | 
 
 | 
3817
 | 
     my $self = shift;  | 
| 
121
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6496
 | 
     $self->_extract_doubles('shp_X', 'shp_Y');  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $self->{shp_points} = [Geo::ShapeFile::Point->new(  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         X => $self->{shp_X},  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Y => $self->{shp_Y},  | 
| 
125
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9582
 | 
     )];  | 
| 
126
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4401
 | 
     $self->{shp_num_points} = 1;  | 
| 
127
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4660
 | 
     $self->{shp_x_min} = $self->{shp_X};  | 
| 
128
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4816
 | 
     $self->{shp_x_max} = $self->{shp_X};  | 
| 
129
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4157
 | 
     $self->{shp_y_min} = $self->{shp_Y};  | 
| 
130
 | 
2553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4122
 | 
     $self->{shp_y_max} = $self->{shp_Y};  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  Point  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double        X       // X coordinate  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double        Y       // Y coordinate  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PolyLine {  | 
| 
137
 | 
2253
 | 
 
 | 
 
 | 
  
2253
  
 | 
 
 | 
3604
 | 
     my $self = shift;  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
139
 | 
2253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5337
 | 
     $self->_extract_bounds();  | 
| 
140
 | 
2253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5169
 | 
     $self->_extract_parts_and_points();  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PolyLine  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[4]             Box         // Bounding Box  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer               NumParts    // Number of parts  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer               NumPoints   // Number of points  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer[NumParts]     Parts       // Index to first point in part  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point[NumPoints]      Points      // Points for all parts  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_Polygon {  | 
| 
150
 | 
2607
 | 
 
 | 
 
 | 
  
2607
  
 | 
 
 | 
3757
 | 
     my $self = shift;  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
152
 | 
2607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5782
 | 
     $self->_extract_bounds();  | 
| 
153
 | 
2607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5771
 | 
     $self->_extract_parts_and_points();  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  Polygon  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[4]          Box        // Bounding Box  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer            NumParts   // Number of Parts  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer            NumPoints  // Total Number of Points  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer[NumParts]  Parts      // Index to First Point in Part  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point[NumPoints]   Points     // Points for All Parts  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_MultiPoint {  | 
| 
163
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
10
 | 
     my $self = shift;  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     $self->_extract_bounds();  | 
| 
166
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $self->_extract_ints('little', 'shp_num_points');  | 
| 
167
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
     $self->_extract_points($self->{shp_num_points}, 'shp_points');  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  MultiPoint  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[4]          Box        // Bounding Box  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer            NumPoints  // Number of Points  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point[NumPoints]   Points     // The points in the set  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PointZ {  | 
| 
175
 | 
2445
 | 
 
 | 
 
 | 
  
2445
  
 | 
 
 | 
3905
 | 
     my $self = shift;  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
177
 | 
2445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5752
 | 
     $self->_parse_shp_Point();  | 
| 
178
 | 
2445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5697
 | 
     $self->_extract_doubles('shp_Z', 'shp_M');  | 
| 
179
 | 
2445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8686
 | 
     $self->{shp_points}->[0]->Z($self->{shp_Z});  | 
| 
180
 | 
2445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6893
 | 
     $self->{shp_points}->[0]->M($self->{shp_M});  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PointZ  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point +  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double Z  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double M  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PolyLineZ {  | 
| 
188
 | 
366
 | 
 
 | 
 
 | 
  
366
  
 | 
 
 | 
585
 | 
     my $self = shift;  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
190
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
839
 | 
     $self->_parse_shp_PolyLine();  | 
| 
191
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1030
 | 
     $self->_extract_z_data();  | 
| 
192
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
791
 | 
     $self->_extract_m_data();  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PolyLineZ  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # PolyLine +  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             Z Range  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     Z Array  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             M Range  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     M Array  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PolygonZ {  | 
| 
202
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_Polygon();  | 
| 
205
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_z_data();  | 
| 
206
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PolygonZ  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Polygon +  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             Z Range  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     Z Array  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             M Range  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     M Array  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_MultiPointZ {  | 
| 
216
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_MultiPoint();  | 
| 
219
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_z_data();  | 
| 
220
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  MultiPointZ  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # MultiPoint +  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]         Z Range  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints] Z Array  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]         M Range  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints] M Array  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PointM {  | 
| 
230
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
232
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_Point();  | 
| 
233
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_doubles('shp_M');  | 
| 
234
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{shp_points}->[0]->M($self->{shp_M});  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PointM  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point +  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double M // M coordinate  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PolyLineM {  | 
| 
241
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
243
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_PolyLine();  | 
| 
244
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PolyLineM  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # PolyLine +  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             MRange      // Bounding measure range  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     MArray      // Measures for all points  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_PolygonM {  | 
| 
252
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
254
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_Polygon();  | 
| 
255
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  PolygonM  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Polygon +  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]             MRange      // Bounding Measure Range  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]     MArray      // Measures for all points  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_MultiPointM {  | 
| 
263
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
265
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_parse_shp_MultiPoint();  | 
| 
266
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  MultiPointM  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # MultiPoint  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]         MRange      // Bounding measure range  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints] MArray      // Measures  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _parse_shp_MultiPatch {  | 
| 
274
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $self = shift;  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
276
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_bounds();  | 
| 
277
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_parts_and_points();  | 
| 
278
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_z_data();  | 
| 
279
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->_extract_m_data();  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # MultiPatch  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[4]           BoundingBox  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer             NumParts  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer             NumPoints  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer[NumParts]   Parts  | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Integer[NumParts]   PartTypes  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Point[NumPoints]    Points  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]           Z Range  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]   Z Array  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[2]           M Range  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Double[NumPoints]   M Array  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_bounds {  | 
| 
294
 | 
4863
 | 
 
 | 
 
 | 
  
4863
  
 | 
 
 | 
6580
 | 
     my $self = shift;  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
296
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10981
 | 
     $self->_extract_doubles(qw/shp_x_min shp_y_min shp_x_max shp_y_max/);  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_ints {  | 
| 
300
 | 
19695
 | 
 
 | 
 
 | 
  
19695
  
 | 
 
 | 
26719
 | 
     my $self = shift;  | 
| 
301
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24851
 | 
     my $end = shift;  | 
| 
302
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36552
 | 
     my @what = @_;  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
304
 | 
19695
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
61372
 | 
     my $template = ($end =~ /^l/i) ? 'V' :'N';  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
306
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39733
 | 
     $self->_extract_and_unpack(4, $template, @what);  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_count_ints {  | 
| 
310
 | 
4860
 | 
 
 | 
 
 | 
  
4860
  
 | 
 
 | 
6734
 | 
     my $self = shift;  | 
| 
311
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6383
 | 
     my $count = shift;  | 
| 
312
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6308
 | 
     my $end = shift;  | 
| 
313
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6891
 | 
     my $label = shift;  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
315
 | 
4860
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12500
 | 
     my $template = ($end =~ /^l/i) ? 'V' :'N';  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
317
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11176
 | 
     my $tmp = substr $self->{shp_data}, 0, ($count * 4), '';  | 
| 
318
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12139
 | 
     my @tmp = unpack $template . $count, $tmp;  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #my @tmp = unpack($template."[$count]",$tmp);  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
321
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15504
 | 
     $self->{$label} = [@tmp];  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_doubles {  | 
| 
325
 | 
10593
 | 
 
 | 
 
 | 
  
10593
  
 | 
 
 | 
14172
 | 
     my $self = shift;  | 
| 
326
 | 
10593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20692
 | 
     my @what = @_;  | 
| 
327
 | 
10593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14280
 | 
     my $size = 8;  | 
| 
328
 | 
10593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13691
 | 
     my $template = 'd';  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
330
 | 
10593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19408
 | 
     foreach ( @what ) {  | 
| 
331
 | 
30912
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53381
 | 
         my $tmp = substr $self->{shp_data}, 0, $size, '';  | 
| 
332
 | 
30912
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
78404
 | 
         $self->{ $_ } = $little_endian_sys  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ? (unpack $template, $tmp )  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             : (unpack $template, scalar reverse $tmp );  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_count_doubles {  | 
| 
339
 | 
732
 | 
 
 | 
 
 | 
  
732
  
 | 
 
 | 
1006
 | 
     my $self = shift;  | 
| 
340
 | 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1011
 | 
     my $count = shift;  | 
| 
341
 | 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1060
 | 
     my $label = shift;  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
343
 | 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1539
 | 
     my $tmp = substr $self->{shp_data}, 0, $count*8, '';  | 
| 
344
 | 
732
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2136
 | 
     my @tmp = $little_endian_sys  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? (unpack 'd'.$count, $tmp )  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : (reverse unpack( 'd' . $count, scalar ( reverse( $tmp ) ) ) );  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3096
 | 
     $self->{$label} = [@tmp];  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_points {  | 
| 
352
 | 
4863
 | 
 
 | 
 
 | 
  
4863
  
 | 
 
 | 
7010
 | 
     my $self = shift;  | 
| 
353
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6351
 | 
     my $count = shift;  | 
| 
354
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7021
 | 
     my $label = shift;  | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
356
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11491
 | 
     my $data = substr $self->{shp_data}, 0, $count * 16, '';  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
358
 | 
4863
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29600
 | 
     my @ps = $little_endian_sys  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? (unpack 'd*', $data )  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : (reverse unpack 'd*', scalar reverse $data );  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
362
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8610
 | 
     my @p = (); # points  | 
| 
363
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11131
 | 
     while(@ps) {  | 
| 
364
 | 
80764
 | 
 
 | 
 
 | 
 
 | 
 
 | 
138151
 | 
         my ($x, $y) = (shift @ps, shift @ps);  | 
| 
365
 | 
80764
 | 
 
 | 
 
 | 
 
 | 
 
 | 
164158
 | 
         push @p, Geo::ShapeFile::Point->new(X => $x, Y => $y);  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
367
 | 
4863
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33732
 | 
     $self->{$label} = [@p];  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_and_unpack {  | 
| 
371
 | 
19695
 | 
 
 | 
 
 | 
  
19695
  
 | 
 
 | 
25333
 | 
     my $self = shift;  | 
| 
372
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24298
 | 
     my $size = shift;  | 
| 
373
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23669
 | 
     my $template = shift;  | 
| 
374
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33388
 | 
     my @what = @_;  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
376
 | 
19695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32993
 | 
     foreach(@what) {  | 
| 
377
 | 
31971
 | 
 
 | 
 
 | 
 
 | 
 
 | 
73917
 | 
         my $tmp = substr $self->{shp_data}, 0, $size, '';  | 
| 
378
 | 
31971
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
58656
 | 
         if ( $template eq 'd' ) {  | 
| 
379
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $tmp = Geo::ShapeFile->byteswap( $tmp );  | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
381
 | 
31971
 | 
 
 | 
 
 | 
 
 | 
 
 | 
88979
 | 
         $self->{$_} = unpack $template, $tmp;  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
385
 | 
4644
 | 
 
 | 
 
 | 
  
4644
  
 | 
  
1
  
 | 
17317
 | 
 sub num_parts { shift()->{shp_num_parts}; }  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parts {  | 
| 
387
 | 
4751
 | 
 
 | 
 
 | 
  
4751
  
 | 
  
0
  
 | 
12893
 | 
     my $self = shift;  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
389
 | 
4751
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7573
 | 
     my $parts = $self->{shp_parts};  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
391
 | 
4751
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8827
 | 
     return wantarray ? @{$parts || []} : $parts;  | 
| 
 
 | 
4666
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
14228
 | 
    | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
394
 | 
4626
 | 
 
 | 
 
 | 
  
4626
  
 | 
  
1
  
 | 
2664213
 | 
 sub num_points { shift()->{shp_num_points}; }  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub points {  | 
| 
396
 | 
4711
 | 
 
 | 
 
 | 
  
4711
  
 | 
  
1
  
 | 
14063
 | 
     my $self = shift;  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
398
 | 
4711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7645
 | 
     my $points = $self->{shp_points};  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
400
 | 
4711
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9769
 | 
     return wantarray ? @{$points || []} : $points;  | 
| 
 
 | 
4626
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
19552
 | 
    | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_part {  | 
| 
404
 | 
85
 | 
 
 | 
 
 | 
  
85
  
 | 
  
1
  
 | 
123
 | 
     my $self  = shift;  | 
| 
405
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
129
 | 
     my $index = shift;  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
407
 | 
85
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
175
 | 
     croak 'index passed to get_part must be >0'  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if $index <= 0;  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
410
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
123
 | 
     $index -= 1; # shift to a 0 index  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #  $parts is an array of starting indexes in the $points array  | 
| 
413
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
150
 | 
     my $parts  = $self->parts;  | 
| 
414
 | 
85
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
205
 | 
     croak 'index exceeds number of parts'  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if $index > $#$parts;  | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
417
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
208
 | 
     my $points = $self->points;  | 
| 
418
 | 
85
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
251
 | 
     my $beg    = $parts->[$index]   || 0;  | 
| 
419
 | 
85
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
229
 | 
     my $end    = $parts->[$index+1] || 0;  #  if we use 5.010 then we can use the // operator here  | 
| 
420
 | 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
120
 | 
     $end -= 1;  | 
| 
421
 | 
85
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
174
 | 
     if ($end < 0) {  | 
| 
422
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
         $end = $#$points;  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
85
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2389
 | 
     return wantarray ? @$points[$beg .. $end] : [@$points[$beg .. $end]];  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub shape_type {  | 
| 
429
 | 
4626
 | 
 
 | 
 
 | 
  
4626
  
 | 
  
1
  
 | 
15179
 | 
     my $self = shift;  | 
| 
430
 | 
4626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9441
 | 
     return $self->{shp_shape_type};  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub shape_id {  | 
| 
434
 | 
604
 | 
 
 | 
 
 | 
  
604
  
 | 
  
1
  
 | 
753
 | 
     my $self = shift;  | 
| 
435
 | 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1857
 | 
     return $self->{shp_record_number};  | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_z_data {  | 
| 
439
 | 
366
 | 
 
 | 
 
 | 
  
366
  
 | 
 
 | 
522
 | 
     my $self = shift;  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
441
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
875
 | 
     $self->_extract_doubles('shp_z_min', 'shp_z_max');  | 
| 
442
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
950
 | 
     $self->_extract_count_doubles($self->{shp_num_points}, 'shp_z_data');  | 
| 
443
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
574
 | 
     my @zdata = @{delete $self->{shp_z_data}};  | 
| 
 
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1287
 | 
    | 
| 
444
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1220
 | 
     for (0 .. $#zdata) {  | 
| 
445
 | 
5208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11196
 | 
         $self->{shp_points}->[$_]->Z($zdata[$_]);  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_m_data {  | 
| 
450
 | 
366
 | 
 
 | 
 
 | 
  
366
  
 | 
 
 | 
539
 | 
     my $self = shift;  | 
| 
451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
452
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
823
 | 
     $self->_extract_doubles ('shp_m_min', 'shp_m_max');  | 
| 
453
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
859
 | 
     $self->_extract_count_doubles($self->{shp_num_points}, 'shp_m_data');  | 
| 
454
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
562
 | 
     my @mdata = @{delete $self->{shp_m_data}};  | 
| 
 
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
870
 | 
    | 
| 
455
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
993
 | 
     for (0 .. $#mdata) {  | 
| 
456
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{shp_points}->[$_]->M($mdata[$_]);  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _extract_parts_and_points {  | 
| 
461
 | 
4860
 | 
 
 | 
 
 | 
  
4860
  
 | 
 
 | 
7295
 | 
     my $self = shift;  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
463
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10374
 | 
     $self->_extract_ints('little', 'shp_num_parts', 'shp_num_points');  | 
| 
464
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13794
 | 
     $self->_extract_count_ints($self->{shp_num_parts}, 'little', 'shp_parts');  | 
| 
465
 | 
4860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14606
 | 
     $self->_extract_points($self->{shp_num_points}, 'shp_points');  | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  these could be factory generated  | 
| 
470
 | 
5164
 | 
 
 | 
 
 | 
  
5164
  
 | 
  
1
  
 | 
12892
 | 
 sub x_min { shift()->{shp_x_min}; }  | 
| 
471
 | 
5164
 | 
 
 | 
 
 | 
  
5164
  
 | 
  
1
  
 | 
11647
 | 
 sub x_max { shift()->{shp_x_max}; }  | 
| 
472
 | 
5164
 | 
 
 | 
 
 | 
  
5164
  
 | 
  
1
  
 | 
12532
 | 
 sub y_min { shift()->{shp_y_min}; }  | 
| 
473
 | 
5164
 | 
 
 | 
 
 | 
  
5164
  
 | 
  
1
  
 | 
13853
 | 
 sub y_max { shift()->{shp_y_max}; }  | 
| 
474
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 sub z_min { shift()->{shp_z_min}; }  | 
| 
475
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 sub z_max { shift()->{shp_z_max}; }  | 
| 
476
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 sub m_min { shift()->{shp_m_min}; }  | 
| 
477
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 sub m_max { shift()->{shp_m_max}; }  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub bounds {  | 
| 
480
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
12
 | 
     my $self = shift;  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
482
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     my @results = (  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->x_min,  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->y_min,  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->x_max,  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->y_max,  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     return wantarray ? @results : \@results;  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub has_point {  | 
| 
493
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my $self  = shift;  | 
| 
494
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $point = shift;  | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
496
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return 0 if !$self->bounds_contains_point($point);  | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
498
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $check_pt ($self->points) {  | 
| 
499
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         return 1 if $check_pt == $point;  | 
| 
500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
502
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return 0;  | 
| 
503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub contains_point {  | 
| 
506
 | 
59
 | 
 
 | 
 
 | 
  
59
  
 | 
  
1
  
 | 
327
 | 
     my ( $self, $point, $index_res ) = @_;  | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
508
 | 
59
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
155
 | 
     return $self->_contains_point_use_index ($point, $index_res)  | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if $self->get_spatial_index || defined $index_res;  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
511
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
109
 | 
     return 0 if !$self->bounds_contains_point( $point );  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
513
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
     my $a = 0;  | 
| 
514
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
     my ( $x0, $y0 ) = ( $point->get_x, $point->get_y );  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #  one day we will track the bounds of the parts  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #  so we can more easily skip parts of multipart polygons  | 
| 
518
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
     my $num_parts = $self->num_parts;  | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #  $x1, $x2, $y1 and $y2 are offsets from the point we are checking  | 
| 
521
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     foreach my $part_num (1 .. $num_parts) {  | 
| 
522
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
129
 | 
         my $points = $self->get_part( $part_num );  | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
524
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
105
 | 
         my $p_start = shift @$points;  #  $points is a copy, so no harm in shifting  | 
| 
525
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
181
 | 
         my $x1 = $p_start->get_x - $x0;  | 
| 
526
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
127
 | 
         my $y1 = $p_start->get_y - $y0;  | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
528
 | 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
113
 | 
         foreach my $p2 ( @$points ) {  | 
| 
529
 | 
1986
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3360
 | 
             my $x2 = $p2->get_x - $x0;  | 
| 
530
 | 
1986
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3340
 | 
             my $y2 = $p2->get_y - $y0;  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #  does the ray intersect the segment?  | 
| 
533
 | 
1986
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3676
 | 
             if (($y2 >= 0) != ($y1 >= 0)) {  #  $y0 is between $y1 and $y2  | 
| 
534
 | 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
96
 | 
                 my $isl = $x1 * $y2 - $y1 * $x2;  #  is left of $p2  | 
| 
535
 | 
52
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
102
 | 
                 if ( $y2 > $y1 ) {  | 
| 
536
 | 
26
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
64
 | 
                     if ($isl > 0) {  | 
| 
537
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
                         $a--;  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 else {  | 
| 
541
 | 
26
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
59
 | 
                     if ($isl < 0) {  | 
| 
542
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
                         $a++;  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
546
 | 
1986
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3118
 | 
             ( $x1, $y1 ) = ( $x2, $y2 );  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
550
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
     return $a;  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _contains_point_use_index {  | 
| 
554
 | 
37
 | 
 
 | 
 
 | 
  
37
  
 | 
 
 | 
103
 | 
     my ( $self, $point, $index_res ) = @_;  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
556
 | 
37
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
153
 | 
     return 0 if !$self->bounds_contains_point( $point );  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
558
 | 
33
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
104
 | 
     my $sp_index_hash = $self->get_spatial_index || $self->build_spatial_index ($index_res);  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
560
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
     my $a = 0;  | 
| 
561
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
93
 | 
     my ( $x0, $y0 ) = ( $point->get_x, $point->get_y );  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
563
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
96
 | 
     my @parts = $self->parts;  | 
| 
564
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72
 | 
     my $num_parts = scalar @parts;  | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #  $x1, $x2, $y1 and $y2 are offsets from the point we are checking  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   PART:  | 
| 
568
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
     foreach my $part_index (1 .. $num_parts) {  | 
| 
569
 | 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
180
 | 
         my $sp_index = $sp_index_hash->{$part_index};  | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
571
 | 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
229
 | 
         my @results = $sp_index->query_point($x0, $y0);  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         #  skip if not in this part's bounding box  | 
| 
574
 | 
81
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
498
 | 
         next PART if !scalar @results;  | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # segments spanning the index's bounding box  | 
| 
577
 | 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
115
 | 
         for my $segment (@results) {  | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #  index stores bare x and y coords to avoid method overhead here  | 
| 
580
 | 
22962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42597
 | 
             my $x1 = $segment->[0][0] - $x0;  | 
| 
581
 | 
22962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31213
 | 
             my $y1 = $segment->[0][1] - $y0;  | 
| 
582
 | 
22962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34699
 | 
             my $x2 = $segment->[1][0] - $x0;  | 
| 
583
 | 
22962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31397
 | 
             my $y2 = $segment->[1][1] - $y0;  | 
| 
584
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
585
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #  does the ray intersect the segment?  | 
| 
586
 | 
22962
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44917
 | 
             if (($y2 >= 0) != ($y1 >= 0)) {  | 
| 
587
 | 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
160
 | 
                 my $isl = $x1 * $y2 - $y1 * $x2;  | 
| 
588
 | 
82
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
206
 | 
                 if ( $y2 > $y1 ) {  | 
| 
589
 | 
41
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
138
 | 
                     if ($isl > 0) {  | 
| 
590
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
                         $a--;  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 else {  | 
| 
594
 | 
41
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
109
 | 
                     if ($isl < 0) {  | 
| 
595
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
                         $a++;  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     }  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
602
 | 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
182
 | 
     return $a;  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  We could trigger a build if undefined,  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  but save that for later.    | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_spatial_index {  | 
| 
609
 | 
92
 | 
 
 | 
 
 | 
  
92
  
 | 
  
1
  
 | 
142
 | 
     my $self = shift;  | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
611
 | 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
404
 | 
     return $self->{_spatial_indexes};  | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  Add the polygon's segments to a spatial index  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  where the index boxes are as wide as the part  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  they are in.  | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  The set of spatial indexes is a hash keyed by  | 
| 
618
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  the part ID.  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $n is the number of boxes - need an automatic way of calculating, poss f(y_range / x_range)  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub build_spatial_index {  | 
| 
621
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
3149
 | 
     my $self = shift;  | 
| 
622
 | 
7
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
33
 | 
     my $n    = shift || 10;  | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
624
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     $n = int $n;  | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
626
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     croak 'Cannot build spatial index with <1 boxes'  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       if $n < 1;  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
629
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     my %sp_indexes;  | 
| 
630
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
631
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     my @parts = $self->parts;  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
633
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     my ($x_min, $x_max, $y_min, $y_max);  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
635
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     my $part_id = 0;  | 
| 
636
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     foreach my $part (@parts) {  | 
| 
637
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
         $part_id ++;  #  parts are indexed base 1  | 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
639
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
         my $segments = $self->get_segments ($part_id);  | 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
641
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
67
 | 
         if (@parts > 1) {  | 
| 
642
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
             my %bounds = $self->_get_part_bounds ($part_id);  | 
| 
643
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
             ($x_min, $y_min, $x_max, $y_max) = @bounds{qw /x_min y_min x_max y_max/};  | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
| 
646
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
             ($x_min, $y_min, $x_max, $y_max) = $self->bounds;  #  faster than searching all points  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
649
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
46
 | 
         my $n_boxes = @$segments > 20 ? $n : 1;  | 
| 
650
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
94
 | 
         my $sp_index = $index_class->new ($n_boxes, $x_min, $y_min, $x_max, $y_max);  | 
| 
651
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
652
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
         foreach my $segment (@$segments) {  | 
| 
653
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19611
 | 
             my $p1 = $segment->[0];  | 
| 
654
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14235
 | 
             my $p2 = $segment->[1];  | 
| 
655
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             #  bare metal version  | 
| 
657
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16021
 | 
             my $coords = [  | 
| 
658
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 [$p1->get_x, $p1->get_y],  | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 [$p2->get_x, $p2->get_y],  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ];  | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
662
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15730
 | 
             my @bbox = ($x_min, $y_min, $x_max, $y_max);  | 
| 
663
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15741
 | 
             $sp_index->insert($coords, @bbox);  | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
666
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5733
 | 
         $sp_indexes{$part_id} = $sp_index;  | 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
669
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15897
 | 
     $self->{_spatial_indexes} = \%sp_indexes;  | 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
671
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
111
 | 
     return wantarray ? %sp_indexes : \%sp_indexes;  | 
| 
672
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
673
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
674
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _get_part_bounds {  | 
| 
675
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
10
 | 
     my $self = shift;  | 
| 
676
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     my $part = shift;  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
678
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     my $points = $self->get_part($part);  | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
680
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     my $pt1 = shift @$points;  | 
| 
681
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     my ($x_min, $y_min) = ($pt1->get_x, $pt1->get_y);  | 
| 
682
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     my ($x_max, $y_max) = ($x_min, $y_min);  | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
684
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     foreach my $pt (@$points) {  | 
| 
685
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
409
 | 
         my $x = $pt->get_x;  | 
| 
686
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
387
 | 
         my $y = $pt->get_y;  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
688
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
356
 | 
         $x_min = min ($x_min, $x);  | 
| 
689
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
322
 | 
         $y_min = min ($y_min, $y);  | 
| 
690
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
351
 | 
         $x_max = max ($x_max, $x);  | 
| 
691
 | 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
731
 | 
         $y_max = max ($y_max, $y);  | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
694
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     my %bounds = (  | 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         x_min => $x_min,  | 
| 
696
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         x_max => $x_max,  | 
| 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         y_min => $y_min,  | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         y_max => $y_max,  | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
701
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
54
 | 
     return wantarray ? %bounds : \%bounds;  | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_segments {  | 
| 
705
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
22
 | 
     my $self = shift;  | 
| 
706
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     my $part = shift;  | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
708
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
     my $points = $self->get_part($part);  | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
710
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     my @segments;  | 
| 
711
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
     foreach my $i (0 .. $#$points - 1) {  | 
| 
712
 | 
7289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16244
 | 
         push @segments, [$points->[$i], $points->[$i+1]];  | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
715
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
373
 | 
     return wantarray ? @segments : \@segments;  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub vertex_centroid {  | 
| 
719
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
720
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $part = shift;  | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
722
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my ($cx, $cy) = (0, 0);  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
724
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @points = ();  | 
| 
725
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ($part) {  | 
| 
726
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @points = $self->get_part($part);  | 
| 
727
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
728
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
729
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @points = $self->points;  | 
| 
730
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
732
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     foreach (@points) {  | 
| 
733
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $cx += $_->X;  | 
| 
734
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $cy += $_->Y;  | 
| 
735
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
736
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Geo::ShapeFile::Point->new(  | 
| 
738
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         X => $cx / @points,  | 
| 
739
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Y => $cy / @points,  | 
| 
740
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *centroid = \&vertex_centroid;  | 
| 
743
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
744
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub area_centroid {  | 
| 
745
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my ( $self, $part ) = @_;  | 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
747
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my ( $cx, $cy ) = ( 0, 0 );  | 
| 
748
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $A = 0;  | 
| 
749
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
750
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my (@points, @parts);  | 
| 
751
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
752
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ( defined $part ) {  | 
| 
753
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @parts = ( $part );  | 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
755
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
756
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         @parts = (1 .. $self->num_parts);  | 
| 
757
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
758
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
759
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for my $part ( @parts ) {  | 
| 
760
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my ( $p0, @pts )  = $self->get_part( $part );  | 
| 
761
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my ( $x0, $y0 )   = ( $p0->X, $p0->Y );  | 
| 
762
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my ( $x1, $y1 )   = ( 0, 0 );  | 
| 
763
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my ( $cxp, $cyp ) = ( 0, 0 );  | 
| 
764
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $Ap = 0;  | 
| 
765
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
766
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         for ( @pts ) {  | 
| 
767
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             my $x2 = $_->X - $x0;  | 
| 
768
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             my $y2 = $_->Y - $y0;  | 
| 
769
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $Ap  += ( my $a = $x2*$y1 - $x1*$y2 );  | 
| 
770
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $cxp += $a * ( $x2 + $x1 ) / 3;  | 
| 
771
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $cyp += $a * ( $y2 + $y1 ) / 3;  | 
| 
772
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ( $x1, $y1 ) = ( $x2, $y2 );  | 
| 
773
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
774
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
775
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $cx += $Ap * $x0 + $cxp;  | 
| 
776
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $cy += $Ap * $y0 + $cyp;  | 
| 
777
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $A += $Ap;  | 
| 
778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
779
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
780
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return Geo::ShapeFile::Point->new(  | 
| 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         X => $cx / $A,  | 
| 
782
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         Y => $cy / $A,  | 
| 
783
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
784
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
785
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
786
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dump {  | 
| 
787
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
 
 | 
     my $self = shift;  | 
| 
788
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
789
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $return = '';  | 
| 
790
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
791
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #$self->points();  | 
| 
792
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #$self->get_part();  | 
| 
793
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #$self->x_min, x_max, y_min, y_max, z_min, z_max, m_min, m_max  | 
| 
794
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
795
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $return .= sprintf  | 
| 
796
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "Shape Type: %s (id: %d)  Parts: %d   Points: %d\n",  | 
| 
797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->shape_type_text(),  | 
| 
798
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->shape_id(),  | 
| 
799
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->num_parts(),  | 
| 
800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->num_points();  | 
| 
801
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
802
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $return .= sprintf  | 
| 
803
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "\tX bounds(min=%s, max=%s)\n",  | 
| 
804
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->x_min(),  | 
| 
805
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->x_max();  | 
| 
806
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
807
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $return .= sprintf  | 
| 
808
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         "\tY bounds(min=%s, max=%s)\n",  | 
| 
809
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->y_min(),  | 
| 
810
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->y_max();  | 
| 
811
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
812
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if (defined $self->z_min() && defined $self->z_max()) {  | 
| 
813
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $return .= sprintf  | 
| 
814
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             "\tZ bounds(min=%s, max=%s)\n",  | 
| 
815
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->z_min(),  | 
| 
816
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->z_max();  | 
| 
817
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
818
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
819
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
     if (defined $self->m_min() && defined $self->m_max()) {  | 
| 
820
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $return .= sprintf  | 
| 
821
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             "\tM bounds(min=%s, max=%s)\n",  | 
| 
822
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->m_min(),  | 
| 
823
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->m_max();  | 
| 
824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
825
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
826
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (1 .. $self->num_parts()) {  | 
| 
827
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $return .= "\tPart $_:\n";  | 
| 
828
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         foreach ($self->get_part($_)) {  | 
| 
829
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $return .= "\t\t$_\n";  | 
| 
830
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
831
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
832
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
833
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $return .= "\n";  | 
| 
834
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
835
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $return;  | 
| 
836
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
837
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
838
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
839
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |