Last active
November 3, 2019 20:03
-
-
Save mdamien/71d03478fe66782e0863284eab387184 to your computer and use it in GitHub Desktop.
GeoSteiner output parser and import to blender
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
FST (Full Steiner tree) generator Version 3 parser | |
Documentation: http://geosteiner.com/geosteiner-5.1-manual.pdf (page 186) | |
How to use: "./rand_points 10 | ./efst | ./bb -f | python3 fst2json.py" | |
To note, an alternate method is to grep for the " % @C XXX YYY" output from `bb`, | |
to get the Steiner points. (page 158 of the manual) | |
""" | |
import json | |
try: | |
input = raw_input | |
except NameError: | |
pass | |
def line(): | |
return input().replace('\t', ' ').strip() | |
METRICS = ['Rectilinear', 'Euclidean', 'Graph'] | |
FST_STATUS = ["never needed", "maybe needed", "always needed"] | |
data = { | |
"version": line(), | |
"instance": line(), | |
"metric": METRICS[int(line())], | |
"number_of_terminals": int(line()), | |
"length_minimum_steiner_tree": float(line().split()[0]), | |
"scaling_factor": line(), | |
"decimal_integrality": float(line().split()[0]), | |
"machine": line(), | |
"cpu_time": int(line()), | |
"number_of_FSTs": int(line()), | |
"terminals_coords": [], | |
"terminal_is_not_a_steiner_point": [], | |
"fsts": [], | |
} | |
for _ in range(data["number_of_terminals"]): | |
x, y = line().split()[:2] | |
data["terminals_coords"].append([ | |
float(x), | |
float(y), | |
]) | |
data["terminal_is_not_a_steiner_point"] = [int(x) for x in line().split()] | |
for _ in range(data["number_of_FSTs"]): | |
fst_data = { | |
"number_of_terminals": int(line()), | |
"terminals_indices": [int(x) for x in line().split()], | |
"length": float(line().split()[0]), | |
"n_steiner": int(line()), | |
"steiner_coords": [], | |
} | |
for _ in range(fst_data["n_steiner"]): | |
x, y = line().split()[:2] | |
fst_data["steiner_coords"].append([ | |
float(x), | |
float(y), | |
]) | |
fst_data["n_edges"] = int(line()) | |
fst_data["edges"] = [] | |
for _ in range(fst_data["n_edges"]): | |
origin, dest = line().split() | |
fst_data["edges"].append([int(origin), int(dest)]) | |
fst_data["status"] = FST_STATUS[int(line())] | |
fst_data["n_incompatible_fsts"] = int(line()) | |
if fst_data["n_incompatible_fsts"]: | |
fst_data["incompatible_fsts"] = line().split() | |
data["fsts"].append(fst_data) | |
print(json.dumps(data, indent=2)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# based on http://wiki.theprovingground.org/blender-py-mathmesh | |
# and https://askubuntu.com/questions/325485/how-to-make-a-mesh-by-using-python-script-on-blender#325515 | |
import bpy | |
import math | |
from pprint import pprint as pp | |
import json | |
# clear mesh and object | |
for item in bpy.context.scene.objects: | |
if item.type == 'MESH': | |
bpy.context.scene.objects.unlink(item) | |
for item in bpy.data.objects: | |
if item.type == 'MESH': | |
bpy.data.objects.remove(item) | |
for item in bpy.data.meshes: | |
bpy.data.meshes.remove(item) | |
for item in bpy.data.materials: | |
bpy.data.materials.remove(item) | |
data_path = "/path/to/your/fst2json/output" | |
data = json.load(open(data_path)) | |
pp(data) | |
# mesh arrays | |
verts = [] | |
faces = [] | |
edges = [] | |
# get real index of the point (page 181 of the manual) | |
def conv(fst, x): | |
# terminal | |
if x > 0: return fst["terminals_indices"][x - 1] - 1 | |
# steiner point | |
if x < 0: return len(verts) - len(fst["steiner_coords"]) - x - 1 | |
for x, y in data["terminals_coords"]: | |
verts.append((x, y, 0)) | |
for fst in data["fsts"]: | |
for x, y in fst["steiner_coords"]: | |
verts.append((x, y, 0)) | |
print('len verts', len(verts)) | |
for org, dst in fst["edges"]: | |
print('edge', org, dst) | |
org, dst = conv(fst, org), conv(fst, dst) | |
print(' ->', org, dst) | |
edges.append((org, dst)) | |
print(verts) | |
print(edges) | |
# sanity check to avoid crashes | |
for org, dst in edges: | |
if not (len(verts) > org >= 0 and len(verts) > dst >= 0): | |
print("verts=", len(verts), "org=", org, "dst=", dst) | |
ooops | |
#create mesh and object | |
mesh = bpy.data.meshes.new("steiner-tree") | |
object = bpy.data.objects.new("steiner-tree",mesh) | |
#set mesh location | |
object.location = bpy.context.scene.cursor_location | |
bpy.context.scene.objects.link(object) | |
#create mesh from python data | |
mesh.from_pydata(verts, edges,faces) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment