~meshing/meshing/urop

« back to all changes in this revision

Viewing changes to shape/extractPoints.py

  • Committer: Adam Candy
  • Date: 2012-07-06 15:30:52 UTC
  • Revision ID: adam.candy@imperial.ac.uk-20120706153052-63q7bbtir43ts2vp
Import of Varun's branch lp:~varun-verma11/+junk/gshhstoshp into the folder 'shape'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Sets the read and the write file stream according to
 
3
the command line arguments given.
 
4
 
 
5
The first argument specifies which shape file the user
 
6
wants to specify the boundaries of
 
7
 
 
8
The second arguments specifies the boundary polygon
 
9
 
 
10
The third argument specifies the file path to which the
 
11
new shape has to be written
 
12
"""
 
13
 
 
14
 
 
15
from shapely.ops import cascaded_union
 
16
import shapefile
 
17
from shapely.geometry import *
 
18
import sys
 
19
import matplotlib.pyplot as pyplot
 
20
 
 
21
"""
 
22
Write the results to .shp.
 
23
"""
 
24
def writeShapeFile(points, filepath) :
 
25
        #begin the instance pf writer class
 
26
        w = shapefile.Writer()
 
27
        #ensure shape and records the balance
 
28
        w.autobalance = 1
 
29
        i = 0
 
30
        for l in points:
 
31
                pList = []
 
32
                pList.append(l)
 
33
                if len(l)==1 :
 
34
                        w.point(pList[0][0],pList[0][1])
 
35
                        w.field("%d_FLD"%i,"C","40")    
 
36
                        i+=1
 
37
                elif len(l)==2 :
 
38
                        w.line(parts = pList)
 
39
                        w.field("%d_FLD"%i,"C","40")            
 
40
                        i+=1
 
41
                else :
 
42
                        w.poly(parts = pList)
 
43
                        w.field("%d_FLD"%i,"C","40")
 
44
                        i += 1
 
45
        w.save(filepath)
 
46
        print("Number of shapes Written %d" %i)
 
47
 
 
48
 
 
49
"""
 
50
Used if there is only one shape in the boundary shapefile.
 
51
"""
 
52
def getBoundaryPointsList(bounds):
 
53
        shapes = bounds.shapes()
 
54
        pointsList = (shapes[0].points)
 
55
        polygon = Polygon(pointsList)
 
56
        return (polygon,pointsList)
 
57
 
 
58
"""
 
59
When more than one shapefile, works out which objects from the .shp file are overlapping and return the exterior coords of this new shape.
 
60
"""
 
61
def overlap (bounds, plot = False):
 
62
# Read shapefile and work out overlap. Optional plot.
 
63
        shapes = bounds.shapes()
 
64
        pointsList = []
 
65
        for i in range(len(shapes)):
 
66
                # Check datapoint is valid.
 
67
                pointsList.append(shapes[i].points)
 
68
 
 
69
        # Turn the points into polygons.
 
70
        polygons = []
 
71
        for j in range(len(pointsList)):
 
72
                polygons.append(Polygon([pointsList[j][i] for i in range(len(pointsList[j]))]))
 
73
 
 
74
        # Add overlapping shapes into a list so we know which to join together.
 
75
        overlapping = []
 
76
        for n in range(len(polygons) - 1):
 
77
                if polygons[n].intersects(polygons[n+1]) == True: 
 
78
                        # Two if statements to make sure the same polygon isn't being entered more than once.
 
79
                        if polygons[n] not in overlapping: overlapping.append(polygons[n]) 
 
80
                        if polygons[n + 1] not in overlapping: overlapping.append(polygons[n + 1]) 
 
81
 
 
82
        # Create a new shape from the overlapping shapes.
 
83
        join = cascaded_union(overlapping)
 
84
        poly = [join]
 
85
 
 
86
        # Take the coords. of the perimeter of this new shape.
 
87
        coords = []
 
88
        for i in range(len(join.exterior.coords)):
 
89
                coords.append(list(join.exterior.coords[i]))
 
90
 
 
91
 
 
92
        # Plot results if True. Store x-y coords of the perimeter in two lists to plot.
 
93
        if plot == True:
 
94
                x = []; y = []
 
95
                for i in range(len(coords)):
 
96
                        x.append(coords[i][0]); y.append(coords[i][1])
 
97
 
 
98
                # Plot results.
 
99
                pyplot.plot(x, y)
 
100
                pyplot.xlim(-4, 4)
 
101
                pyplot.ylim(-4, 4)
 
102
                pyplot.show()
 
103
        return join, coords
 
104
 
 
105
 
 
106
 
 
107
"""
 
108
Output the final results as a .geo file.
 
109
"""
 
110
def write_geo (coords, filename):
 
111
# Write new shape to .geo.
 
112
        print coords
 
113
 
 
114
        target = open("%s.geo" % filename, "w") # Creates .geo file to write to.
 
115
        for i in range(len(coords)):
 
116
                # Write point.
 
117
                target.write('Point(%d) = {%.3f, %.3f, 0, %.3f};\n' %(i + 1, coords[i][0], coords[i][1], 1.0))
 
118
                # Write the lines connecting the sequential points.
 
119
                if (i + 1 > 1): target.write('Line(%d) = {%d, %d};\n' % (i, i, i + 1))
 
120
        # Connect first and last points.
 
121
        target.write('Line(%d) = {%d, %d};\n' % (i + 1, 1, i + 1))
 
122
        target.close()
 
123
        return False
 
124
 
 
125
 
 
126
assert len(sys.argv)==5, "Incorrect Number of Arguments passed"
 
127
 
 
128
readPath = sys.argv[1]
 
129
boundaryPath = sys.argv[2]
 
130
writePath = sys.argv[3]
 
131
areaThreshold = float(sys.argv[4])
 
132
 
 
133
#input stream for the given shape
 
134
sf = shapefile.Reader(readPath)
 
135
 
 
136
#shapes contained in the given file
 
137
shapes = sf.shapes();
 
138
 
 
139
#boundary = bounds.shapes[0]
 
140
boundary = shapefile.Reader(boundaryPath)
 
141
 
 
142
if (len(boundary.shapes()) > 1): boundaryPolygons, boundaryPointList1 = overlap(boundary); boundaryPointList = [boundaryPointList1]
 
143
else: boundaryPolygons, boundaryPointList = getBoundaryPointsList(boundary)
 
144
 
 
145
"""
 
146
Takes shape from shapefile and converts to a Shapely Polygon. Checks if this polygon lies within the boundary using a.intersect(b). If it does it will perform a.intersection(b) operation returning a Polygon/MultiPolygon which lies within the boundary and then plots result.
 
147
"""
 
148
shapeList = []
 
149
for shape in shapes:
 
150
        x = []; y = []; shp = []
 
151
        polygon = Polygon([shape.points[i] for i in range(len(shape.points))])
 
152
        if (polygon.intersects(boundaryPolygons)):
 
153
                intersection = boundaryPolygons.intersection(polygon)
 
154
                if intersection.area >= areaThreshold:
 
155
 
 
156
                        if intersection.geom_type == 'Polygon':
 
157
                                for i in range(len(list(intersection.exterior.coords))):
 
158
                                        x.append(intersection.exterior.coords[i][0]); y.append(intersection.exterior.coords[i][1])
 
159
                                        pyplot.plot(x, y)
 
160
                                        shp.append([intersection.exterior.coords[i][0], intersection.exterior.coords[i][1]])
 
161
 
 
162
                        if intersection.geom_type == 'MultiPolygon':
 
163
                                for j in range(len(intersection)):
 
164
                                        for i in range(len(list(intersection[j].exterior.coords))):
 
165
                                                x.append(intersection[j].exterior.coords[i][0]); y.append(intersection[j].exterior.coords[i][1])
 
166
                                                pyplot.plot(x, y)
 
167
                                                shp.append([intersection[j].exterior.coords[i][0], intersection[j].exterior.coords[i][1]])
 
168
                        shapeList.append(shp)
 
169
writeShapeFile(shapeList, writePath)
 
170
 
 
171
# Plot boundary.
 
172
x=[]
 
173
y=[]
 
174
 
 
175
for i in range(len(boundaryPointList)):
 
176
        x.append(boundaryPointList[i][0]); y.append(boundaryPointList[i][1])
 
177
pyplot.plot(x,y)
 
178
pyplot.xlim(min(x)-1,max(x)+1)
 
179
pyplot.ylim(min(y)-1,max(y)+1)
 
180
 
 
181
pyplot.show()