|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| import os, math, argparse, json, re, traceback, numpy as np, pandas as pd, trimesh, laspy, shutil
|
| import pyautocad, open3d as o3d, seaborn as sns, win32com.client, pythoncom
|
| import matplotlib.pyplot as plt
|
| from scipy.spatial import distance
|
| from tqdm import trange, tqdm
|
| from math import pi
|
|
|
| def get_layer_to_label(cfg, layer):
|
| layers = cfg['layers']
|
| for lay in layers:
|
| if lay['layer'] == layer:
|
| return lay['label']
|
| return ''
|
|
|
| def get_entity_from_acad(entity_names = ['AcDbLine', 'AcDbPolyline', 'AcDbText']):
|
| acad = pyautocad.Autocad(create_if_not_exists=True)
|
| selections = acad.get_selection('Select entities to extract geometry')
|
|
|
| geoms = []
|
| for entity in tqdm(selections):
|
| try:
|
| if entity.EntityName in entity_names:
|
| geoms.append(entity)
|
| except Exception as e:
|
| print(f'error: {e}')
|
| continue
|
|
|
| if not geoms:
|
| print("No entities found in the drawing.")
|
| return
|
|
|
| return geoms
|
|
|
| def get_bbox(polyline):
|
| xmin, ymin, xmax, ymax = polyline[0][0], polyline[0][1], polyline[0][0], polyline[0][1]
|
| for x, y in polyline:
|
| xmin = min(xmin, x)
|
| ymin = min(ymin, y)
|
| xmax = max(xmax, x)
|
| ymax = max(ymax, y)
|
| return (xmin, ymin, xmax, ymax)
|
|
|
| def get_xsections_from_acad(cfg):
|
| entities = get_entity_from_acad()
|
|
|
|
|
| xsec_list = []
|
| xsec_entities = []
|
| for entity in entities:
|
| if entity.Layer == 'Nru_Frame_Crs_Design' and entity.EntityName == 'AcDbPolyline':
|
| polyline = []
|
| vertex_list = entity.Coordinates
|
| for i in range(0, len(vertex_list), 2):
|
| polyline.append((vertex_list[i], vertex_list[i+1]))
|
| if len(polyline) < 2:
|
| continue
|
| bbox = get_bbox(polyline)
|
|
|
| xsec = {'bbox': bbox, 'station': '', 'geom': []}
|
| xsec_list.append(xsec)
|
| else:
|
| xsec_entities.append(entity)
|
| if len(xsec_entities) == 0:
|
| print("No cross section found in the drawing.")
|
| return []
|
|
|
| for xsec in xsec_list:
|
| for entity in xsec_entities:
|
| if entity.EntityName != 'AcDbText':
|
| continue
|
| pt = (entity.InsertionPoint[0], entity.InsertionPoint[1])
|
| bbox = xsec['bbox']
|
| if pt[0] < bbox[0] or pt[1] < bbox[1] or pt[0] > bbox[2] or pt[1] > bbox[3]:
|
| continue
|
| xsec_station = entity.TextString
|
| pattern = r'\d+\+\d+\.\d+'
|
| match = re.search(pattern, xsec_station)
|
| if match:
|
| xsec_station = match.group()
|
| else:
|
| xsec_station = '-1+000.00'
|
| xsec['station'] = xsec_station
|
|
|
| if len(xsec_list) == 0:
|
| xsec = {'bbox': (-9999999999.0, -9999999999.0, 9999999999.0, 9999999999.0), 'station': '0+000.00'}
|
| xsec_list.append(xsec)
|
|
|
| xsec_list = sorted(xsec_list, key=lambda x: x['station'])
|
|
|
|
|
| for xsec in tqdm(xsec_list):
|
| for entity in xsec_entities:
|
| label = get_layer_to_label(cfg, entity.Layer)
|
| if label == '':
|
| continue
|
|
|
| closed = False
|
| polyline = []
|
| if entity.EntityName == 'AcDbLine':
|
| polyline = [entity.StartPoint, entity.EndPoint],
|
| closed = False
|
| elif entity.EntityName == 'AcDbPolyline':
|
| vertex_list = entity.Coordinates
|
| for i in range(0, len(vertex_list), 2):
|
| polyline.append((vertex_list[i], vertex_list[i+1]))
|
| closed = entity.Closed
|
| else:
|
| continue
|
|
|
| xsec_bbox = xsec['bbox']
|
| entity_bbox = get_bbox(polyline)
|
| if entity_bbox[0] < xsec_bbox[0] or entity_bbox[1] < xsec_bbox[1] or entity_bbox[2] > xsec_bbox[2] or entity_bbox[3] > xsec_bbox[3]:
|
| continue
|
|
|
| geo = {
|
| 'label': label,
|
| 'polyline': polyline,
|
| 'closed': closed,
|
| 'earthwork_feature': []
|
| }
|
| xsec['geom'].append(geo)
|
|
|
| return xsec_list
|
|
|
|
|
| _draw_xsection_index = 0
|
| _xsections = None
|
| _plot_ax = None
|
| def draw_xsections(ax, index):
|
| xsec = _xsections[index]
|
| for geo in xsec['geom']:
|
| station = xsec['station']
|
| ax.set_title(f'station: {station}')
|
| polyline = np.array(geo['polyline'])
|
| ax.plot(polyline[:,0], polyline[:,1], label=geo['label'])
|
| ax.set_aspect('equal', 'box')
|
|
|
| def next_button(event):
|
| global _draw_xsection_index, _xsections, _plot_ax
|
| _draw_xsection_index += 1
|
| if _draw_xsection_index >= len(_xsections):
|
| _draw_xsection_index = 0
|
| _plot_ax.clear()
|
| draw_xsections(_plot_ax, _draw_xsection_index)
|
|
|
| def prev_button(event):
|
| global _draw_xsection_index, _xsections, _plot_ax
|
| _draw_xsection_index -= 1
|
| if _draw_xsection_index < 0:
|
| _draw_xsection_index = len(_xsections) - 1
|
| _plot_ax.clear()
|
| draw_xsections(_plot_ax, _draw_xsection_index)
|
|
|
| def on_key_press(event):
|
| if event.key == 'right':
|
| next_button(None)
|
| elif event.key == 'left':
|
| prev_button(None)
|
|
|
| def show_xsections(xsections):
|
| from matplotlib.widgets import Button
|
| global _draw_xsection_index, _xsections, _plot_ax
|
| _xsections = xsections
|
|
|
| fig = plt.figure()
|
| _plot_ax = fig.subplots()
|
| plt.subplots_adjust(left = 0.3, bottom = 0.25)
|
| draw_xsections(_plot_ax, _draw_xsection_index)
|
|
|
|
|
| axprev = fig.add_axes([0.7, 0.05, 0.1, 0.075])
|
| bprev = Button(axprev, 'prev', color="white")
|
| bprev.on_clicked(prev_button)
|
| axnext = fig.add_axes([0.81, 0.05, 0.1, 0.075])
|
| bnext = Button(axnext, 'next', color="white")
|
| bnext.on_clicked(next_button)
|
|
|
| fig.canvas.mpl_connect('key_press_event', on_key_press)
|
|
|
| plt.show()
|
|
|
| def main():
|
| parser = argparse.ArgumentParser(description='create earthwork train dataset')
|
| parser.add_argument('--config', type=str, default='config.json', help='config file')
|
| parser.add_argument('--output', type=str, default='output/', help='output directory')
|
| parser.add_argument('--view', type=str, default='output/chain_chunk_6.json', help='view file')
|
|
|
| args = parser.parse_args()
|
| try:
|
| if len(args.view) > 0:
|
| with open(args.view, 'r') as f:
|
| xsections = json.load(f)
|
| show_xsections(xsections)
|
| return
|
|
|
| cfg = None
|
| with open(args.config, 'r', encoding='utf-8') as f:
|
| cfg = json.load(f)
|
|
|
| chunk_index = 0
|
| file_names = os.listdir(args.output)
|
| if len(file_names):
|
| pattern = r'chain_chunk_(\d+)\.json'
|
| indices = [int(re.match(pattern, file_name).group(1)) for file_name in file_names if re.match(pattern, file_name)]
|
| chunk_index = max(indices) + 1 if indices else 0
|
|
|
| print(file_names)
|
|
|
| while True:
|
| xsections = get_xsections_from_acad(cfg)
|
| if len(xsections) == 0:
|
| break
|
| geo_file = os.path.join(args.output, f'chain_chunk_{chunk_index}.json')
|
| with open(geo_file, 'w') as f:
|
| json.dump(xsections, f, indent=4)
|
| print(f'{geo_file} was saved in {args.output}')
|
| chunk_index += 1
|
| except Exception as e:
|
| print(f'error: {e}')
|
| traceback.print_exc()
|
|
|
| if __name__ == '__main__':
|
| main() |