QGIS/scripts/random_vector.py
2024-11-29 15:38:02 +01:00

160 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
# Generates random shapefile which may be used for benchmarks
import math
import os
import random
import string
import sys
from optparse import OptionParser
from osgeo import ogr
def error(msg):
print(msg)
sys.exit(1)
parser = OptionParser("usage: %prog [options] output")
parser.add_option(
"-t",
"--type",
dest="type",
type="choice",
choices=("point", "line", "polygon"),
default="point",
help="Geometry type",
)
parser.add_option(
"-f",
"--features",
dest="features",
type="int",
default=1000,
help="Number of features",
)
parser.add_option(
"-c",
"--coordinates",
dest="coordinates",
type="int",
default=10,
help="Number of coordinates per feature (lines and polygons)",
)
parser.add_option(
"-a",
"--attributes",
dest="attributes",
type="int",
default=10,
help="Number of attributes",
)
parser.add_option(
"-e",
"--extent",
dest="extent",
type="string",
default="-180,-90,180,90",
help="Extent",
)
(options, args) = parser.parse_args()
if len(args) != 1:
error("Output file path missing")
(minx, miny, maxx, maxy) = map(float, options.extent.split(","))
driverName = "ESRI Shapefile"
drv = ogr.GetDriverByName(driverName)
if drv is None:
error("%s driver not available.\n" % driverName)
# delete if exists
try:
if os.path.exists(args[0]):
drv.DeleteDataSource(args[0])
except:
pass
ds = drv.CreateDataSource(args[0])
if ds is None:
error("Creation of output file failed.\n")
types = {"point": ogr.wkbPoint, "line": ogr.wkbLineString, "polygon": ogr.wkbPolygon}
lyr = ds.CreateLayer("out", None, types[options.type])
if lyr is None:
error("Layer creation failed.\n")
attrTypes = (ogr.OFTString, ogr.OFTInteger, ogr.OFTReal)
stringWidth = 100
for a in range(0, options.attributes):
attrName = "attr%s" % a
field_defn = ogr.FieldDefn(attrName, random.choice(attrTypes))
if field_defn.type == ogr.OFTString:
field_defn.SetWidth(stringWidth)
if lyr.CreateField(field_defn) != 0:
error("Creating Name field failed.\n")
feat_defn = lyr.GetLayerDefn()
for f in range(options.features):
feat = ogr.Feature(feat_defn)
buffer = (maxx - minx) / 100
if options.type == "point":
geo = ogr.Geometry(ogr.wkbPoint)
x = random.uniform(minx, maxx)
y = random.uniform(miny, maxy)
geo.SetPoint_2D(0, x, y)
elif options.type == "line":
geo = ogr.Geometry(ogr.wkbLineString)
xc = random.uniform(minx + buffer, maxx - buffer)
yc = random.uniform(miny + buffer, maxy - buffer)
for c in range(options.coordinates):
a = c * 2 * math.pi / options.coordinates
r = random.uniform(buffer / 10, 9 * buffer / 10)
x = xc + r * math.sin(a)
y = yc + r * math.cos(a)
geo.SetPoint_2D(c, x, y)
elif options.type == "polygon":
ring = ogr.Geometry(ogr.wkbLinearRing)
xc = random.uniform(minx + buffer, maxx - buffer)
yc = random.uniform(miny + buffer, maxy - buffer)
for c in range(options.coordinates):
a = c * 2 * math.pi / options.coordinates
r = random.uniform(buffer / 10, 9 * buffer / 10)
x = xc + r * math.sin(a)
y = yc + r * math.cos(a)
ring.SetPoint_2D(c, x, y)
geo = ogr.Geometry(ogr.wkbPolygon)
geo.AddGeometry(ring)
feat.SetGeometry(geo)
for i in range(feat_defn.GetFieldCount()):
field_defn = feat_defn.GetFieldDefn(i)
val = None
limit = 10000000
if field_defn.GetType() == ogr.OFTString:
nChars = random.randint(0, stringWidth)
val = "".join(
random.choice(string.ascii_letters + string.digits)
for x in range(nChars)
)
elif field_defn.GetType() == ogr.OFTInteger:
val = random.randint(-limit, limit)
elif field_defn.GetType() == ogr.OFTReal:
val = random.uniform(-limit, limit)
feat.SetField(field_defn.name, val)
if lyr.CreateFeature(feat) != 0:
error("Failed to create feature in shapefile.\n")