Skip to content

Instantly share code, notes, and snippets.

@JeffJacobson
Created January 3, 2012 17:58
Show Gist options
  • Save JeffJacobson/1556089 to your computer and use it in GitHub Desktop.
Save JeffJacobson/1556089 to your computer and use it in GitHub Desktop.
simplegeometry: A module for working with OGC Simple Geometry definitions. Designed for use with SQL Server 2008 WKT strings.
"""
simplegeometry
A module for working with OGC Simple Geometry definitions.
Designed for use with SQL Server 2008 WKT strings.
"""
import re
## Examples from wikipedia (http://en.wikipedia.org/wiki/Simple_Features):
##Point
##Example: POINT (10 10)
##LineString
##Example: LINESTRING( 10 10, 20 20, 30 40)
##Polygon
##Example: POLYGON ((10 10, 10 20, 20 20, 20 15, 10 10))
##Multipoint
##Example: MULTIPOINT(10 10, 20 20)
##Multipolygon
##Example: MULTIPOLYGON(((10 10, 10 20, 20 20, 20 15, 10 10)),((60 60, 70 70, 80 60, 60 60)))
##GeomCollection
##Example: GEOMETRYCOLLECTION(POINT (10 10), POINT(30 30), LINESTRING(15 15, 20 20))
## Other Examples
##MultiLineString
##MULTILINESTRING ((1065881.7179999948 226211.61200000346 NULL 23, 1065855.9469999969 226264.74099999666 NULL 23.011, 1065768.9370000064 226410.57400000095 NULL 23.044, 1065684.3789999932 226538.02500000596 NULL 23.073, 1065578.9860000014 226678.95600000024 NULL 23.107, 1065457.6630000025 226826.0150000006 NULL 23.143, 1065328.6669999957 226970.0530000031 NULL 23.18, 1065047.123999998 227279.44599999487 NULL 23.259, 1064775.0649999976 227569.88799999654 NULL 23.334, 1064455.2119999975 227887.29000000656 NULL 23.42, 1064162.3199999928 228172.82899999619 NULL 23.497, 1063542.2220000029 228770.86800000072 NULL 23.66, 1062923.3490000069 229365.2310000062 NULL 23.822, 1062300.799999997 229965.72100000083 NULL 23.986, 1062247.623999998 230017.08499999344 NULL 24))
# Matches a single point definition
_pointre = re.compile(r"""(?P<x>-?\d+(?:\.\d+)?)
\s+
(?P<y>-?\d+(?:\.\d+)?)
(?:
(?:
\s+
(?P<z>(?:-?\d+(?:\.\d+)?)|(?:NULL))
)
(?:
\s+
(?P<m>(?:-?\d+(?:\.\d+)?)|(?:NULL))
)?
)?""", re.VERBOSE | re.IGNORECASE)
# Matches a comma-separated list of points.
_multipointre = re.compile(r"""(?P<point>
(?P<x>-?\d+(?:\.\d+)?)
\s+
(?P<y>-?\d+(?:\.\d+)?)
(?:
(?:
\s+
(?P<z>(?:-?\d+(?:\.\d+)?)|(?:NULL))
)
(?:
\s+
(?P<m>(?:-?\d+(?:\.\d+)?)|(?:NULL))
)?
)?
(?:,\s*)?
)+""", re.VERBOSE | re.IGNORECASE)
_multipointNoCaptureRe = re.compile(r"""(?x)(?:
(?:-?\d+(?:\.\d+)?)
\s+
(?:-?\d+(?:\.\d+)?)
(?:
(?:
\s+
(?:(?:-?\d+(?:\.\d+)?)|(?:NULL))
)
(?:
\s+
(?:(?:-?\d+(?:\.\d+)?)|(?:NULL))
)?
)?
(?:,\s*)?
)+""")
_wktPointHeaderRe = re.compile(r"(?ix)POINT")
_wktLineStringHeaderRe = re.compile(r"(?ix)LINESTRING")
_wktPolygonHeaderRe = re.compile(r"(?ix)POLYGON")
_wktMultPointHeaderRe = re.compile(r"(?ix)MULTIPOINT")
_wktMultiLineStringHeaderRe = re.compile(r"(?ix)MULTILINESTRING")
_wktMultiPolygonHeaderRe = re.compile(r"(?ix)MULTIPOLYGON")
_wktGeometryCollectionHeaderRe = re.compile(r"(?ix)GEOMETRYCOLLECTION")
_wktMultiOrSingleLineStringHeaderRe = re.compile(r"(?i)^(?:MULTI)?LINESTRING")
_nullRe = re.compile("(?i)NULL")
def _stringToFloat(floatstring):
"""Attempts to parse a string into a float via python's
float() method. If the string is not a number, None is returned.
"""
if floatstring is None or _nullRe.match(floatstring):
return None
try:
return float(floatstring)
except ValueError:
return None
def _pointstringToFloatArray(pointstring):
"""Converts a string into an array of floats.
The array will contain up to four elements:
X, Y, Z and M. The Z and M values may either be null or missing.
"""
return map(_stringToFloat, pointstring.split())
def _linestringToFloatArrays(linestring):
"""Splits a string of points (e.g., LINESTRING)
into a jagged array of doubles. Each outer array
represents a line segment, each inner array contains
x, y, z, and m coordinates, respectively. (Z and M coordinates
may be None if those values were not provided in the line string.)
"""
# 1. Split a line string into an array of strings each representing one point.
# 2. Strip leading and trailing spaces from these arrays.
# 3. Convert the array of strings into an array of doubles with two to
# four elements each.
return map(_pointstringToFloatArray, linestring.split(","))
def parseline(wkt):
"""Parses a string containing one or more line strings into
a jagged array.
The returned array contains these levels of arrays
LineStrings
Points
Coordinates:
Elements are floating point numbers:
X, Y, Z and M. Z and M may also be None.
"""
if not _wktMultiOrSingleLineStringHeaderRe.match(wkt):
raise "Invalid WKT string."
matches = _multipointNoCaptureRe.findall(wkt)
return map(_linestringToFloatArrays, matches)
import simplegeometry
parsedG = simplegeometry.parseline("MULTILINESTRING ((1208120.9130000025 745513.05599999428 NULL 20, 1208147.5579999983 746483.423999995 NULL 20.182, 1208156.1369999945 746685.62999999523 NULL 20.22, 1208167.1659999937 746871.90399999917 NULL 20.255, 1208183.0980000049 747065.53200000525 NULL 20.292, 1208224.0849999934 747534.46500000358 NULL 20.38, 1208278.5320000052 748175.35199999809 NULL 20.503, 1208298.1400000006 748436.38099999726 NULL 20.553, 1208316.5219999999 748766.0380000025 NULL 20.616, 1208325.6720000058 748994.7880000025 NULL 20.66, 1208329.1790000051 749297.90999999642 NULL 20.719, 1208322.6490000039 749569.95900000632 NULL 20.772, 1208314.0709999949 749826.0869999975 NULL 20.822, 1208285.8959999979 750428.78900000453 NULL 20.94, 1208283.375 750469.80500000715 NULL 20.95, 1208271.1790000051 750746.43000000715 NULL 20.999, 1208265.050999999 751041.77300000191 NULL 21.05, 1208273.4159999937 751666.8180000037 NULL 21.16, 1208281.0789999962 752090.83499999344 NULL 21.242, 1208287.1099999994 752659.42000000179 NULL 21.353, 1208292.1659999937 752773.86499999464 NULL 21.375, 1208298.2939999998 752862.099999994 NULL 21.392, 1208308.0980000049 752960.13899999857 NULL 21.411, 1208326.4800000042 753075.33499999344 NULL 21.434, 1208343.2600000054 753156.27799999714 NULL 21.45, 1208365.6959999949 753261.6099999994 NULL 21.47, 1208390.2049999982 753349.84499999881 NULL 21.487, 1208413.4899999946 753428.27699999511 NULL 21.503, 1208440.451000005 753517.73700000346 NULL 21.52, 1208477.3349999934 753615.72900000215 NULL 21.54, 1208517.6560000032 753717.49199999869 NULL 21.562, 1208556.8719999939 753805.72800000012 NULL 21.581, 1208602.2150000036 753896.41400000453 NULL 21.602, 1208656.1369999945 753994.45299999416 NULL 21.624, 1208710.0579999983 754090.04099999368 NULL 21.646, 1208772.5579999983 754186.85500000417 NULL 21.67, 1208833.8330000043 754277.54099999368 NULL 21.692, 1208901.2349999994 754364.550999999 NULL 21.714, 1209017.3530000001 754501.872999996 NULL 21.75, 1209105.8920000046 754597.3939999938 NULL 21.775, 1209185.548999995 754677.050999999 NULL 21.796, 1209248.048999995 754735.875 NULL 21.812, 1210129.2779999971 755567.873999998 NULL 22.04, 1211171.8279999942 756558.49500000477 NULL 22.3, 1211287.2970000058 756665.91599999368 NULL 22.331, 1211621.2600000054 756985.23899999261 NULL 22.42, 1212472.1879999936 757790.05200000107 NULL 22.65, 1212691.0629999936 757995.06599999964 NULL 22.704, 1213056.2590000033 758344.33100000024 NULL 22.795, 1213335.6710000038 758609.03599999845 NULL 22.864, 1213563.7639999986 758833.89300000668 NULL 22.921, 1213681.2590000033 758961.97800000012 NULL 22.953, 1213764.5929999948 759062.46799999475 NULL 22.976, 1213828.3180000037 759147.02699999511 NULL 22.995, 1213900.6219999939 759243.84000000358 NULL 23.017, 1213971.701000005 759354.13400000334 NULL 23.04, 1214022 759434.98199999332 NULL 23.058, 1214086.8969999999 759547.76199999452 NULL 23.081, 1214136.3059999943 759641.92000000179 NULL 23.1, 1214184.9360000044 759736.48700000346 NULL 23.122, 1214235.1809999943 759849.23199999332 NULL 23.147, 1214267.0439999998 759931.34000000358 NULL 23.165, 1214308.7099999934 760039.18299999833 NULL 23.188, 1214336.6809999943 760125.89900000393 NULL 23.207, 1214361.4060000032 760210.752000004 NULL 23.225, 1214389.5929999948 760319.82099999487 NULL 23.248, 1214412.8770000041 760422.76199999452 NULL 23.269, 1214436.1529999971 760526.60500000417 NULL 23.291, 1214453.3180000037 760632.32099999487 NULL 23.313, 1214465.5729999989 760731.58499999344 NULL 23.333, 1214472.925999999 760832.076000005 NULL 23.354, 1214481.7360000014 760961.96899999678 NULL 23.38, 1214485.1809999943 761057.56599999964 NULL 23.398, 1214485.1809999943 761160.50699999928 NULL 23.418, 1214481.5039999932 761442.37000000477 NULL 23.472, 1214466.798999995 762044.08499999344 NULL 23.587, 1214452.0569999963 762740.65600000322 NULL 23.72, 1214421.9950000048 763989.97599999607 NULL 23.95, 1214420.0219999999 764044.79700000584 NULL 23.96, 1214351.6030000001 767105.3599999994 NULL 24.543, 1214350.3770000041 767295.31100000441 NULL 24.579, 1214356.5039999932 767510.99699999392 NULL 24.62, 1214366.3079999983 767707.076000005 NULL 24.657, 1214387.1420000046 767900.70299999416 NULL 24.695, 1214411.6519999951 768090.65399999917 NULL 24.731, 1214452.0929999948 768322.27199999988 NULL 24.776, 1214645.7199999988 769318.59499999881 NULL 24.969, 1214677.2189999968 769478.32799999416 NULL 25))")
for g in parsedG:
for g1 in g:
print g1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment