File Coverage

blib/lib/Geo/E00.pm
Criterion Covered Total %
statement 14 226 6.1
branch 1 80 1.2
condition 1 3 33.3
subroutine 5 17 29.4
pod 0 14 0.0
total 21 340 6.1


line stmt bran cond sub pod time code
1             # Geo::E00
2             #
3             # Arc/Info Export (E00) parser.
4             #
5             # Copyright (c) 2002-2003 Tower Technologies s.r.l.
6             # All Rights Reserved
7             #
8              
9              
10              
11             package Geo::E00;
12              
13 1     1   5706 use strict;
  1         3  
  1         40  
14              
15 1     1   6 use Carp;
  1         2  
  1         175  
16 1     1   1048 use IO::File;
  1         16321  
  1         3438  
17              
18             $Geo::E00::VERSION = '0.05';
19              
20             # Constructor
21             sub new
22             {
23 1     1 0 10 my ($proto) = @_;
24              
25 1   33     7 my $class = ref($proto) || $proto;
26              
27 1         5 return bless {
28             'FH' => undef,
29             }, $class;
30             }
31              
32             sub open
33             {
34 1     1 0 8 my ($self, $file) = @_;
35              
36 1 50       4 return undef unless defined $file;
37              
38 0           $self->{'FH'} = new IO::File $file, 'r';
39              
40 0           return $self->{'FH'};
41             }
42              
43             sub parse
44             {
45 0     0 0   my ($self) = @_;
46 0           my ($fn);
47              
48 0           my $fh = $self->{'FH'};
49              
50 0 0         return undef unless defined $fh;
51              
52             # Read the first line
53 0           my $headline = $fh->getline;
54              
55 0 0         return undef unless defined $headline;
56              
57             # print STDERR $headline;
58              
59 0 0         return undef unless $headline =~ m|^EXP\s+(\d+)\s+(.+)\s*$|;
60              
61 0           $self->{'VERSION'} = $1;
62 0           $self->{'EXPFILE'} = $2;
63              
64             # print STDERR "Version $self->{'VERSION'} , file $self->{'EXPFILE'}\n";
65              
66 0           my $data = {};
67              
68 0           while (my $line = $fh->getline)
69             {
70 0 0         if ($line =~ m|^([A-Z]{3})\s+(\d+)|)
71             {
72             # Section start
73              
74 0           my $section = $1;
75 0           my $param = $2;
76              
77             # print STDERR "Got section: $section, $param\n";
78              
79 0 0         $data->{'arc'} = $self->parse_arc($fh, $param) if $section eq 'ARC';
80 0 0         $data->{'cnt'} = $self->parse_cnt($fh, $param) if $section eq 'CNT';
81 0 0         $data->{'lab'} = $self->parse_lab($fh, $param) if $section eq 'LAB';
82 0 0         $data->{'tol'} = $self->parse_tol($fh, $param) if $section eq 'TOL';
83 0 0         $data->{'tx7'} = $self->parse_tx7($fh, $param) if $section eq 'TX7';
84 0 0         $data->{'log'} = $self->parse_log($fh, $param) if $section eq 'LOG';
85 0 0         $data->{'prj'} = $self->parse_prj($fh, $param) if $section eq 'PRJ';
86 0 0         $data->{'pal'} = $self->parse_pal($fh, $param) if $section eq 'PAL';
87 0 0         $data->{'ifo'} = $self->parse_ifo($fh, $param) if $section eq 'IFO';
88             }
89             }
90 0           $data = combine($data);
91              
92 0           return $data;
93             }
94              
95             sub parse_arc
96             {
97 0     0 0   my ($self, $fh) = @_;
98              
99 0           my @sets = ();
100              
101 0           while (my $line = $fh->getline)
102             {
103             # Check for termination pattern
104 0 0         last if $line =~ m|^\s*-1(\s+0){6}|;
105              
106             # Set header
107 0 0         if ($line =~ m|^\s*(\d+)\s+(\-?\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)|)
108             {
109 0           my $arc = {
110             'cov-num' => $1,
111             'cov-id' => $2,
112             'node-from' => $3,
113             'node-to' => $4,
114             'poly-left' => $5,
115             'poly-right' => $6,
116             'npoints' => $7,
117             };
118            
119 0           my @coords = ();
120 0           my @llcoords = ();
121              
122             # print STDERR "NUM: $arc->{'cov-num'}, ID: $arc->{'cov-id'}, PAIRS: $arc->{'npoints'}\n";
123              
124 0           for (my $i = 0; $i < $arc->{'npoints'};)
125             {
126             # Get a new line
127              
128 0           my $cline = $fh->getline;
129              
130             # Check if this is a 2 pairs line
131              
132 0 0         if ($cline =~ m{^(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+|-]\d+)})
133             {
134 0           $llcoords[$i]->{'x'}=$1;
135 0           $llcoords[$i]->{'y'}=$2;
136 0           $llcoords[$i+1]->{'x'}=$3;
137 0           $llcoords[$i+1]->{'y'}=$4;
138            
139 0           push(@coords, $1, $2, $3, $4);
140              
141             # print STDERR " got 2 pairs line\n";
142 0           $i += 2;
143              
144 0           next;
145             }
146              
147             # 1 pair line
148              
149 0 0         if ($cline =~ m{^(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)})
150             {
151 0           $llcoords[$i]->{'x'}=$1;
152 0           $llcoords[$i]->{'y'}=$2;
153 0           push(@coords, $1, $2);
154              
155             # print STDERR " got 1 pair line\n";
156 0           $i += 1;
157              
158 0           next;
159             }
160              
161 0           Carp::croak "Unknown pair line: $cline\n";
162             }
163              
164 0 0         Carp::croak "Wrong number of x-y pairs in ARC <> $arc->{'npoints'}\n"
165             unless ((scalar @coords) / 2 ) eq $arc->{'npoints'};
166              
167 0           $arc->{'points'} = \@coords;
168 0           $arc->{'coord'} = \@llcoords;
169              
170 0           push(@sets, $arc);
171              
172 0           next;
173             }
174            
175 0           Carp::croak "Unknown set line: $line";
176             }
177            
178             # print STDERR Data::Dumper->Dump( [ \@sets ] );
179              
180             # print STDERR "END ARC SECTION\n";
181              
182 0           return \@sets;
183             }
184              
185             sub parse_cnt
186             {
187 0     0 0   my ($self, $fh) = @_;
188              
189 0           my @sets = ();
190              
191 0           while (my $line = $fh->getline)
192             {
193             # Check for termination pattern
194 0 0         if ($line =~ m{^\s*(\d+)})
195             {
196 0           my $cnt = {
197             'cnt-id' => $1,
198             };
199 0           $line = $fh->getline;
200 0 0         last if $line =~ m|^\s*-1(\s+0){6}|;
201 0 0         if ($line =~ m{^\s*(\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)})
202             {
203 0           $cnt->{ 'x' } = $2;
204 0           $cnt->{ 'y' } = $3;
205             } else {
206 0           Carp::croak "Unknown CNT line: $line\n";
207             }
208            
209             # Store
210 0           push(@sets, $cnt);
211             }
212              
213             }
214            
215 0           return \@sets;
216            
217             }
218              
219              
220             sub parse_lab
221             {
222 0     0 0   my ($self, $fh) = @_;
223              
224 0           my @sets = ();
225              
226 0           while (my $line = $fh->getline)
227             {
228             # Check for termination pattern
229 0 0         last if $line =~ m|^\s*-1\s+0|;
230              
231             # Set header
232 0 0         if ($line =~ m{^\s*(\d+)\s+(\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)})
233             {
234 0           my $lab = {
235             'cov-id' => $1,
236             'poly-id' => $2,
237             'x' => $3,
238             'y' => $4,
239             };
240            
241             # Read and throw away the next line
242 0           $fh->getline;
243              
244             # Store
245 0           push(@sets, $lab);
246              
247             # Next set...
248 0           next;
249             }
250            
251 0           Carp::croak "Unknown set line: $line";
252             }
253            
254 0           return \@sets;
255             }
256              
257             sub parse_tol
258 0     0 0   {
259             # print STDERR "END TOL SECTION\n";
260             }
261              
262             sub parse_tx7
263 0     0 0   {
264             # print STDERR "END TX7 SECTION\n";
265             }
266              
267             sub parse_log
268             {
269 0     0 0   my ($self, $fh) = @_;
270              
271 0           my @sets = ();
272              
273 0           while (my $line = $fh->getline)
274             {
275 0 0         last if $line =~ m|^EOL|;
276            
277 0           my ($year,$month,$day,$hour,$minute,$connecttime,$cputime,$iotime,$commandline)=unpack(
278             "a4 a2 a2 a2 a2 a4 a6 a6 a*",$line);
279 0           my $log = {
280             'year' => $year,
281             'month' => $month,
282             'day' => $day,
283             'hour' => $hour,
284             'minute' => $minute,
285             'connecttime' => $connecttime,
286             'cputime' => $cputime,
287             'iotime' => $iotime,
288             'commandline' => $commandline,
289             };
290              
291             # Read and throw away the next line
292              
293 0           $fh->getline;
294 0           push(@sets, $log);
295             }
296 0           return \@sets;
297             }
298              
299             sub parse_prj
300 0     0 0   {
301             # not needed
302             # print STDERR "END PRJ SECTION\n";
303             }
304              
305             sub parse_ifo
306             {
307 0     0 0   my ($self, $fh, $param) = @_;
308              
309 0           my $data;
310              
311 0           while (my $line = $fh->getline)
312             {
313             # Check for termination pattern
314 0 0         last if $line =~ m|^EOI|;
315 0 0         if ($line =~ m|^(.*)?\.([A-Z]{3})\s+XX\s+(\d+)\s+\d+\s+\d+\s+(\d+)|)
316             {
317 0           my $ifo = {
318             section => $1,
319             name => $2,
320             items => $3,
321             records => $4,
322             lines => 1,
323             };
324              
325 0           my $totallength = 0;
326              
327 0           for (my $i = 0; $i <$ifo->{items}; $i++) {
328 0           my ($itemname,$widthpos,$startpos,$outputformat,$dummy) =
329             split(" ",$fh->getline,6);
330 0           $widthpos =~ s/-1$//;
331 0           $startpos =~ s/4-1$//;
332 0           $outputformat =~ s/-1$//;
333 0 0         if ($outputformat == 12 ) { $outputformat = 14; }
  0            
334 0 0         if ($outputformat == 5 ) { $outputformat = 11; }
  0            
335              
336 0           $totallength += $outputformat;
337 0           $ifo->{format} .= "a$outputformat ";
338 0 0         if ($totallength > 80) {
339 0           $ifo->{lines}++;
340 0           $totallength -= 80;
341             }
342 0           push @{$ifo->{item}},$itemname;
  0            
343             }
344 0           $data->{$ifo->{name}} = $self->parse_types($fh, $ifo);
345             }
346              
347             }
348 0           $data;
349             }
350              
351              
352             sub parse_pal
353             {
354 0     0 0   my ($self, $fh) = @_;
355              
356 0           my @sets = ();
357              
358 0           while (my $line = $fh->getline)
359             {
360             # Check for termination pattern
361 0 0         last if $line =~ m|^\s*-1(\s+0){6}|;
362              
363             # Set header
364 0 0         if ($line =~ m{^\s*(\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+-]\d+)(\s*[ -]\d+\.\d+E[+|-]\d+)})
365             {
366 0           my $pal = {
367             'npoints' => $1,
368             'xmin' => $2,
369             'ymin' => $3,
370             'xmax' => $4,
371             'ymax' => $5,
372             };
373            
374 0           my @points = ();
375              
376 0           for (my $i = 0; $i < $pal->{'npoints'};)
377             {
378             # Get a new line
379              
380 0           my $cline = $fh->getline;
381              
382             # Check if this is a 2 pairs line
383              
384 0 0         if ($cline =~ m{^(\s*[ -]\d+)(\s*[ -]\d+)(\s*[ -]\d+)(\s*[ -]\d+)(\s*[ -]\d+)(\s*[ -]\d+)})
385             {
386 0           $points[$i]->{'arc-number'} = $1;
387 0           $points[$i]->{'node-number'} = $2;
388 0           $points[$i]->{'polygon-number'} = $3;
389 0           $points[$i+1]->{'arc-number'} = $4;
390 0           $points[$i+1]->{'node-number'} = $5;
391 0           $points[$i+1]->{'polygon-number'} = $6;
392              
393             # print STDERR " got 2 pairs line\n";
394 0           $i += 2;
395              
396 0           next;
397             }
398              
399             # 1 pair line
400              
401 0 0         if ($cline =~ m{^(\s*[ -]\d+)(\s*[ -]\d+)(\s*[ -]\d+)})
402             {
403 0           $points[$i]->{'arc-number'} = $1;
404 0           $points[$i]->{'node-number'} = $2;
405 0           $points[$i]->{'polygon-number'} = $3;
406              
407             # print STDERR " got 1 pair line\n";
408 0           $i += 1;
409              
410 0           next;
411             }
412              
413 0           Carp::croak "Unknown pair line: $cline\n";
414             }
415              
416 0 0         Carp::croak "Wrong number of x-y pairs in PAL <> $pal->{'npoints'}\n"
417             unless ((scalar @points) ) eq $pal->{'npoints'};
418              
419 0           $pal->{'points'} = \@points;
420              
421 0           push(@sets, $pal);
422              
423 0           next;
424             }
425            
426 0           Carp::croak "Unknown set line: $line";
427             }
428            
429 0           return \@sets;
430             }
431              
432             sub parse_types
433             {
434 0     0 0   my ($self, $fh, $ifo) = @_;
435              
436 0           my @sets = ();
437              
438 0           for (my $i = 0; $i < $ifo->{'records'}; $i++) {
439 0           my ($types,@ri,$itemsnow);
440 0           $itemsnow = 0;
441 0           while ($itemsnow < $ifo->{'items'}) {
442 0           my ($line,$j,$x);
443 0           for ($j =0; $j < $ifo->{'lines'}; $j++) {
444 0           $x = $fh->getline();chomp($x);
  0            
445 0           $line .= sprintf("%-80s",$x)
446             }
447 0           my (@ri) = unpack($ifo->{format},$line);
448 0           for ($j=0; $j < (@ri); $j++) {
449 0           $ri[$j] =~ s/^ *//;$ri[$j] =~ s/ *$//;
  0            
450 0           $types->{$ifo->{'item'}->[$j+$itemsnow]}=$ri[$j];
451             }
452 0           $itemsnow += (@ri);
453             }
454 0           push(@sets, $types);
455             }
456 0           $ifo->{data}=\@sets;
457 0           return $ifo;
458             }
459              
460             sub combine
461             {
462 0     0 0   my ($data) = @_;
463 0           my ($rarc, $rlab);
464              
465 0 0         if (defined($data->{'arc'})) {
466 0           my $nr = 0;
467 0           my $arc = $data->{arc};
468 0           foreach my $arcline (@$arc) {
469 0           $rarc->{$arcline->{"cov-num"}} = $nr++;
470             }
471             }
472              
473 0 0         if (defined($data->{'lab'})) {
474 0           my $nr = 0;
475 0           my $lab = $data->{lab};
476 0           foreach my $labline (@$lab) {
477 0           $rlab->{$labline->{'poly-id'}} = $nr++;
478             }
479             }
480              
481 0 0         if (defined($data->{'ifo'})) {
482             #___________________________________________________
483             # AAT Part
484             #___________________________________________________
485 0 0         if (defined($data->{'ifo'}->{'AAT'})) {
486 0           my $aat = $data->{'ifo'}->{'AAT'};
487 0           my (@el,$item,$nr);
488             # the next AAT field will be saved in the ARC structure
489             # 0 FNODE#
490             # 1 TNODE#
491             # 2 LPOLY#
492             # 3 RPOLY#
493             # 4 LENGTH saved
494             # 5 RRLINE# < compare with cov_num
495             # 6 RRLINE-ID
496             # 7 .. extra fields
497 0           $nr=0;
498 0           foreach $item (@{$aat->{item}}) {
  0            
499 0           $el[$nr++] = $item;
500             }
501 0           my $dline;
502 0           foreach $dline (@{$aat->{data}}) {
  0            
503 0           $nr = $rarc->{$dline->{$el[5]}};
504 0           $data->{'arc'}->[$nr]->{$el[4]} = $dline->{$el[4]};
505 0           for (my $i = 7; $i <$aat->{items}; $i++) {
506 0           $data->{'arc'}->[$nr]->{$el[$i]} = $dline->{$el[$i]};
507             }
508             }
509            
510             }
511             #___________________________________________________
512             # PAT Part
513             #___________________________________________________
514 0 0         if (defined($data->{'ifo'}->{'PAT'})) {
515 0           my $pat = $data->{'ifo'}->{'PAT'};
516 0           my (@el,$item,$nr);
517             # the next PAT field will be saved in the LAB structure
518             # 0 AREA
519             # 1 PERIMETER
520             # 2 PPPOINT#
521             # 3 PPPOINT-ID
522             # 4 ..
523 0           $nr=0;
524 0           foreach $item (@{$pat->{item}}) {
  0            
525 0           $el[$nr++] = $item;
526             }
527 0           my $dline;
528 0           foreach $dline (@{$pat->{data}}) {
  0            
529              
530 0           $nr = $rlab->{$dline->{$el[2]}};
531 0           for (my $i = 4; $i <$pat->{items}; $i++) {
532 0           $data->{'lab'}->[$nr]->{$el[$i]} = $dline->{$el[$i]};
533             }
534             }
535             }
536             }
537 0           $data;
538             }
539              
540             1;
541              
542             __END__