| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- # -*- coding: utf-8 -*-
- """Convert a survey DWG into GIS feature classes and inventory its layers.
- Run with ArcGIS Desktop's Python 2.7 (arcpy):
- C:\\Python27\\ArcGIS10.8\\python.exe tools/city-massing/convert-dwg-to-gis.py <input.dwg> <out.gdb>
- ArcGIS splits a CAD drawing into Polyline / Polygon / Point / Annotation feature classes and
- records the original CAD layer in a `Layer` field. Nothing is filtered here: the script reports
- what the drawing actually contains, so a building layer can be chosen from evidence.
- """
- import sys
- import os
- import io
- import json
- import arcpy
- def main():
- if len(sys.argv) < 3:
- print('usage: convert-dwg-to-gis.py <input.dwg> <out.gdb> [referenceScale]')
- return 2
- dwg = os.path.abspath(sys.argv[1])
- gdb = os.path.abspath(sys.argv[2])
- # ArcGIS requires a reference scale; survey drawings here are 1:500 topographic sheets.
- reference_scale = sys.argv[3] if len(sys.argv) > 3 else '500'
- if not os.path.exists(dwg):
- print('missing input: %s' % dwg)
- return 2
- work = os.path.dirname(gdb)
- if not os.path.isdir(work):
- os.makedirs(work)
- inventory_only = '--inventory-only' in sys.argv
- if inventory_only:
- if not arcpy.Exists(gdb):
- print('missing geodatabase: %s' % gdb)
- return 2
- else:
- if arcpy.Exists(gdb):
- arcpy.Delete_management(gdb)
- arcpy.CreateFileGDB_management(work, os.path.basename(gdb))
- print('converting %s -> %s (reference scale 1:%s)' % (dwg, gdb, reference_scale))
- arcpy.CADToGeodatabase_conversion(dwg, gdb, 'cad', reference_scale, '')
- arcpy.env.workspace = gdb
- # CADToGeodatabase puts the feature classes inside a feature dataset, so walk both levels.
- targets = []
- for dataset in arcpy.ListDatasets() or []:
- for name in arcpy.ListFeatureClasses(feature_dataset=dataset) or []:
- targets.append((dataset, name))
- for name in arcpy.ListFeatureClasses() or []:
- targets.append((None, name))
- report = {'input': dwg, 'gdb': gdb, 'featureClasses': []}
- for dataset, name in targets:
- entry = {'name': name, 'dataset': dataset, 'featureType': arcpy.Describe(name).shapeType, 'featureCount': 0, 'layers': {}}
- fields = [f.name for f in arcpy.ListFields(name)]
- entry['fields'] = fields
- hasLayer = 'Layer' in fields
- with arcpy.da.SearchCursor(name, ['Layer'] if hasLayer else ['OID@']) as cursor:
- for row in cursor:
- entry['featureCount'] += 1
- if hasLayer:
- key = row[0] if row[0] is not None else u'(none)'
- entry['layers'][key] = entry['layers'].get(key, 0) + 1
- report['featureClasses'].append(entry)
- print('%-10s %-28s %-9s %6d features, %d layers' % (
- dataset or '-', name, entry['featureType'], entry['featureCount'], len(entry['layers'])))
- for layer, count in sorted(entry['layers'].items(), key=lambda kv: -kv[1])[:40]:
- line = u' %6d %s' % (count, layer)
- print(line.encode('utf-8'))
- out = os.path.join(work, os.path.basename(gdb) + '-inventory.json')
- with io.open(out, 'w', encoding='utf-8') as handle:
- handle.write(unicode(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)))
- print('inventory: %s' % out)
- return 0
- if __name__ == '__main__':
- sys.exit(main())
|