source: trunk/mapserver/mapscript/perl/examples/thin.pl

Last change on this file was 5814, checked in by tkralidi, 18 years ago

initial addition

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 3.2 KB
Line 
1#!/usr/bin/perl
2# Script : thin.pl
3#
4# Purpose: An adaption of the ArcView Avenue example script genfeat.ave. It's
5# basically the Douglas-Peucker generalization algorithm.
6# (http://mapserver.gis.umn.edu/community/scripts/thin.pl)
7#
8# $Id: thin.pl 5814 2006-10-30 13:44:44Z tkralidi $
9#
10
11use strict;
12use warnings;
13use POSIX;
14use XBase;
15use mapscript;
16use Getopt::Long;
17use File::Copy;
18
19my ($infile, $outfile, $tolerance);
20
21GetOptions("input=s", \$infile, "output=s", \$outfile, "tolerance=n", \$tolerance);
22
23if(!$infile or !$outfile or !$tolerance) {
24 print "Usage: $0 --input=[filename] --output=[filename] --tolerance=[maximum distance between vertices]\n";
25 exit 0;
26}
27
28die "Tolerance must be greater than zero." unless $tolerance > 0;
29
30# initialize counters for reporting
31my $incount = 0;
32my $outcount = 0;
33
34# open the input shapefile
35my $inSHP = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile.";
36
37die "Cannot thin point/multipoint shapefiles." unless ($inSHP->{type} == 5 or $inSHP->{type} == 3);
38
39# create the output shapefile
40
41unlink "$outfile.shp";
42unlink "$outfile.shx";
43unlink "$outfile.dbf";
44
45my $outSHP = new mapscript::shapefileObj($outfile, $inSHP->{type}) or die "Unable to create shapefile '$outfile'. $!\n";
46
47copy("$infile.dbf", "$outfile.dbf") or die "Can't copy file $infile.dbf to $outfile.dbf: $!\n";
48
49my $inshape = new mapscript::shapeObj(-1); # something to hold shapes
50
51for(my $i=0; $i<$inSHP->{numshapes}; $i++) {
52
53 $inSHP->get($i, $inshape);
54 my $outshape = new mapscript::shapeObj(-1);
55
56 for(my $j=0; $j<$inshape->{numlines}; $j++) {
57
58 my $inpart = $inshape->get($j);
59 my $outpart = new mapscript::lineObj();
60
61 my @stack = ();
62
63 $incount += $inpart->{numpoints};
64
65 my $anchor = $inpart->get(0); # save first point
66 $outpart->add($anchor);
67 my $aIndex = 0;
68
69 my $fIndex = $inpart->{numpoints} - 1;
70 push @stack, $fIndex;
71
72 # Douglas - Peucker algorithm
73 while(@stack) {
74
75 $fIndex = $stack[$#stack];
76 my $fPoint = $inpart->get($fIndex);
77
78 my $max = $tolerance; # comparison values
79 my $maxIndex = 0;
80
81 # process middle points
82 for (($aIndex+1) .. ($fIndex-1)) {
83
84 my $point = $inpart->get($_);
85 #my $dist = $point->distanceToLine($anchor, $fPoint);
86 my $dist = $point->distanceToSegment($anchor, $fPoint);
87
88 if($dist >= $max) {
89 $max = $dist;
90 $maxIndex = $_;
91 }
92 }
93
94 if($maxIndex > 0) {
95 push @stack, $maxIndex;
96 } else {
97 $outpart->add($fPoint);
98 $anchor = $inpart->get(pop @stack);
99 $aIndex = $fIndex;
100 }
101 }
102
103 # check for collapsed polygons, use original data in that case
104 if(($outpart->{numpoints} < 4) and ($inSHP->{type} == 5)) {
105 $outpart = $inpart;
106 }
107
108 $outcount += $outpart->{numpoints};
109 $outshape->add($outpart);
110
111 } # for each part
112
113 $outSHP->add($outshape);
114 undef($outshape); # free memory associated with shape
115
116} # for each shape
117
118$outSHP = ''; # write the file
119
120undef $inSHP;
121undef $outSHP;
122
123my $reduction = ((($outcount / $incount) * 100) - 100) * -1;
124
125print <<END;
126
127$0 Summary:
128
129Input File : $infile ($incount vertices)
130Output File : $outfile ($outcount vertices)
131Tolerance : $tolerance
132Reduction : $reduction%
133
134END
Note: See TracBrowser for help on using the repository browser.