replace cq_toplevel.py --export-svg with --export-png, which uses the same render pipeline as the interactive editor

This commit is contained in:
2024-02-07 04:27:41 +00:00
parent 3afdf11e8f
commit c19431ba1d
2 changed files with 57 additions and 37 deletions

View File

@@ -81,11 +81,11 @@ build/web-viewer/index.html: doc.in/index.html build/web-viewer/vtk.js build/web
mkdir -p build/web-viewer
cp $< $@
%.svg: cq_toplevel.py src/*.py
%.png: cq_toplevel.py src/*.py
mkdir -p "$(@D)"
./cq_toplevel.py --export-svg $@
./cq_toplevel.py --export-png $@
doc: build/web-viewer/index.html build/images/pinephone_front.svg build/images/pinephone_back.svg build/images/pinephone_right.svg
doc: build/web-viewer/index.html build/images/pinephone_case.png
clean:
rm -rf build

View File

@@ -20,29 +20,53 @@ import case
import pinephone
import ldtek_battery
from cadquery.occ_impl.assembly import toVTK
from cadquery.vis import _to_assy, _vtkRenderWindow
from vtkmodules.vtkRenderingCore import vtkRenderWindow, vtkWindowToImageFilter
from vtkmodules.vtkIOImage import vtkPNGWriter
logger = logging.getLogger(__name__)
def svg_export_options(view: str):
proj = (1, 1, 1)
if view == "front":
proj = (0.00, -0.05, 0.10)
elif view == "back":
proj = (0.00, -0.05, -0.10)
elif view == "right":
proj = (-0.10, 0.00, 0.00)
return dict(
width = 1024,
height = 1024,
marginLeft = 100,
marginTop = 10,
showAxes = False,
# projectionDir controls both the angle and the distance from the camera to the model
projectionDir = proj,
strokeWidth = 0.25,
strokeColor = (255, 0, 0),
hiddenColor = (0, 0, 255),
showHidden = True,
)
def export_png_image(obj, file_: str):
# obj = obj.val().scale(2)
# obj = obj.transformed(offset=(0, 0, 0))
assy = _to_assy(obj)
# win = _vtkRenderWindow(assy)
renderer = toVTK(assy)
win = vtkRenderWindow()
# win.SetMultiSamples(16)
# win.SetSize(1024, 1024)
win.AddRenderer(renderer)
win.Render()
camera = renderer.GetActiveCamera()
camera.Roll(-35)
camera.Elevation(-45)
# adjust camera so full object is visible.
# this also resizes the window, potentially changing its aspect ratio.
# it's important that the window has been `Render()`'d at least once by now,
# else it'll adjust the camera based on the wrong aspect ratio.
renderer.ResetCamera()
renderer.SetBackground(0.8, 0.8, 0.8)
# win.SetPosition(-10, 0)
win.Render()
# documented here: <https://examples.vtk.org/site/Python/IO/ImageWriter/>
win_to_input = vtkWindowToImageFilter()
win_to_input.SetInput(win)
# win_to_input.SetScale(5)
# win_to_input.SetViewport(0, 0, 5, 5)
win_to_input.SetInputBufferTypeToRGB()
win_to_input.ReadFrontBufferOff()
win_to_input.Update()
exporter = vtkPNGWriter()
exporter.SetFileName(file_)
exporter.SetInputConnection(win_to_input.GetOutputPort())
exporter.Write()
def _model():
logger.info("computing model ...")
@@ -73,7 +97,7 @@ def main():
parser.add_argument("--render-phone", action="store_true", help="render the case and also the phone within it; useful to confirm fit visually before printing")
parser.add_argument("--render-phone-only", action="store_true", help="render *only* the phone, not even the case")
parser.add_argument("--export-stl")
parser.add_argument("--export-svg")
parser.add_argument("--export-png")
parser.add_argument("--export-vtk")
parser.add_argument("--editor", action="store_true", help="view in cq-editor")
@@ -86,26 +110,22 @@ def main():
os.environ["CASE_RENDER_PHONE_ONLY"] = "1"
if args.export_stl:
model_ = model()
logger.info("exporting stl to %s", args.export_stl)
cq.exporters.export(model(), args.export_stl)
cq.exporters.export(model_, args.export_stl)
if args.export_svg:
view = None
if "front" in args.export_svg:
view = "front"
elif "back" in args.export_svg:
view = "back"
elif "right" in args.export_svg:
view = "right"
logger.info("exporting svg to %s (view: %s)", args.export_svg, str(view))
cq.exporters.export(model(), args.export_svg, opt=svg_export_options(view))
if args.export_png:
model_ = model()
logger.info("exporting png to %s", args.export_png)
export_png_image(model_, args.export_png)
if args.export_vtk:
vtk_file = args.export_vtk
js_var, _ext = os.path.splitext(os.path.basename(vtk_file))
js_file = f'{vtk_file}.js'
model_ = model()
logger.info("exporting VTK (for web rendering) to %s", vtk_file)
cq.exporters.export(model(), vtk_file, cq.exporters.ExportTypes.VTP)
cq.exporters.export(model_, vtk_file, cq.exporters.ExportTypes.VTP)
logger.info("wrapping VTK data in a javascript variable (var %s) in %s", js_var, js_file)
vtk_data = open(vtk_file).read()