prideout / svg3d

generate 3D wireframes as vector art
https://prideout.net/blog/svg_wireframes/
MIT License
353 stars 29 forks source link

How to calculate polygon intersections? #3

Open DBraun opened 3 years ago

DBraun commented 3 years ago

Suppose I have a box and another box that has been shrunk in two dimensions and elongated in the third. The stretched box then intersects the first box, requiring some additional consideration for rendering.

image

It would be cool to support intersections like these if it's not already possible.

import numpy, svg3d, pyrr, math

def get_box_faces(sx, sy, sz):

    verts = numpy.float32(
        [(-1, -1, -1), (-1, -1, 1), (1, -1, 1), (1, -1, -1),
         (-1,  1, -1), (-1,  1, 1), (1,  1, 1), (1,  1, -1),
        ])

    faces = numpy.int32([
        (0, 1, 2, 3),
        (4, 5, 6, 7),
        (0, 1, 5, 4),
        (1, 2, 6, 5),
        (2, 3, 7, 6),
        (3, 0, 4, 7)
        ])

    return 0.5*numpy.float32([sx, sy, sz])*(verts[faces])

def generate_svg(filename):
    view = pyrr.matrix44.create_look_at(
        eye=[50, 40, 120], target=[0, 0, 0], up=[0, 1, 0]
    )
    projection = pyrr.matrix44.create_perspective_projection(
        fovy=15, aspect=1, near=10, far=200
    )
    camera = svg3d.Camera(view, projection)

    style = dict(
        fill="white",
        fill_opacity="0.75",
        stroke="black",
        stroke_linejoin="round",
        stroke_width="0.005",
    )

    faces = numpy.concatenate(
        [get_box_faces(4, 4, 60), get_box_faces(14, 14, 14)]
        )
    print(faces.shape)
    mesh = svg3d.Mesh(faces, style=style)
    view = svg3d.View(camera, svg3d.Scene([mesh]))
    svg3d.Engine([view]).render(filename)

generate_svg("boxes.svg")
villares commented 1 year ago

Cheers @DBraun! I have half a solution, maybe... you could try union with the trimesh library (https://trimsh.org/index.html), I just wouldn't know how to convert the trimesh meshes into the arrays necessary to use svg3D... I'd love to see an example.