"""Rhino 8 Python ScriptEditor: run in a new millimetre document.
Creates separate native box solids and exports named Y-up polygon objects.
Only the newly created geometry is exported; no private document content is read.
"""
import math
import os
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

out = rs.BrowseForFolder(message='Choose a folder for the synthetic Zaaglijst example')
if not out:
    raise SystemExit('Cancelled')
if sc.doc.ModelUnitSystem != Rhino.UnitSystem.Millimeters:
    raise ValueError('Use a millimetre document for this example')

items = []
def timber(name, a, b, width, height):
    x = Rhino.Geometry.Vector3d(b[0]-a[0], b[1]-a[1], b[2]-a[2])
    length = x.Length
    x.Unitize()
    y = Rhino.Geometry.Vector3d.CrossProduct(Rhino.Geometry.Vector3d.ZAxis, x)
    if y.Length < 1e-8:
        y = Rhino.Geometry.Vector3d.YAxis
    y.Unitize()
    plane = Rhino.Geometry.Plane(Rhino.Geometry.Point3d(*a), x, y)
    box = Rhino.Geometry.Box(plane, Rhino.Geometry.Interval(0, length),
                            Rhino.Geometry.Interval(-width/2, width/2),
                            Rhino.Geometry.Interval(-height/2, height/2))
    brep = box.ToBrep()
    attributes = Rhino.DocObjects.ObjectAttributes()
    attributes.Name = name
    sc.doc.Objects.AddBrep(brep, attributes)
    items.append((name, brep))

timber('Rail A', (0, 0, 50), (1200, 0, 50), 80, 100)
timber('Rail B touching A', (1200, 0, 50), (2400, 0, 50), 80, 100)
timber('Rotated brace', (0, 500, 0), (700, 500, 700), 60, 80)
# Deterministic OBJ writer over real Rhino-generated polygon meshes. Equivalent
# axis mapping to "Map Rhino Z to OBJ Y": (x, y, z) -> (x, z, -y).
path = os.path.join(out, 'rhino-frame.obj')
with open(path, 'w') as stream:
    stream.write('# Synthetic Rhino geometry; millimetres, Y up\n')
    offset = 1
    for name, brep in items:
        stream.write('o ' + name.replace(' ', '_') + '\n')
        for mesh in Rhino.Geometry.Mesh.CreateFromBrep(brep, Rhino.Geometry.MeshingParameters.Default):
            mesh.Faces.ConvertQuadsToTriangles()
            for p in mesh.Vertices:
                stream.write('v {:.12g} {:.12g} {:.12g}\n'.format(p.X, p.Z, -p.Y))
            for f in mesh.Faces:
                stream.write('f {} {} {}\n'.format(offset+f.A, offset+f.B, offset+f.C))
            offset += mesh.Vertices.Count
sc.doc.Views.Redraw()
print('Created native Rhino solids and exported ' + path)
