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 mkdir -p build/web-viewer
cp $< $@ cp $< $@
%.svg: cq_toplevel.py src/*.py %.png: cq_toplevel.py src/*.py
mkdir -p "$(@D)" 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: clean:
rm -rf build rm -rf build

View File

@@ -20,29 +20,53 @@ import case
import pinephone import pinephone
import ldtek_battery 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__) logger = logging.getLogger(__name__)
def svg_export_options(view: str): def export_png_image(obj, file_: str):
proj = (1, 1, 1) # obj = obj.val().scale(2)
if view == "front": # obj = obj.transformed(offset=(0, 0, 0))
proj = (0.00, -0.05, 0.10) assy = _to_assy(obj)
elif view == "back": # win = _vtkRenderWindow(assy)
proj = (0.00, -0.05, -0.10) renderer = toVTK(assy)
elif view == "right": win = vtkRenderWindow()
proj = (-0.10, 0.00, 0.00) # win.SetMultiSamples(16)
return dict( # win.SetSize(1024, 1024)
width = 1024, win.AddRenderer(renderer)
height = 1024, win.Render()
marginLeft = 100, camera = renderer.GetActiveCamera()
marginTop = 10, camera.Roll(-35)
showAxes = False, camera.Elevation(-45)
# projectionDir controls both the angle and the distance from the camera to the model # adjust camera so full object is visible.
projectionDir = proj, # this also resizes the window, potentially changing its aspect ratio.
strokeWidth = 0.25, # it's important that the window has been `Render()`'d at least once by now,
strokeColor = (255, 0, 0), # else it'll adjust the camera based on the wrong aspect ratio.
hiddenColor = (0, 0, 255), renderer.ResetCamera()
showHidden = True, 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(): def _model():
logger.info("computing 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", 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("--render-phone-only", action="store_true", help="render *only* the phone, not even the case")
parser.add_argument("--export-stl") parser.add_argument("--export-stl")
parser.add_argument("--export-svg") parser.add_argument("--export-png")
parser.add_argument("--export-vtk") parser.add_argument("--export-vtk")
parser.add_argument("--editor", action="store_true", help="view in cq-editor") 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" os.environ["CASE_RENDER_PHONE_ONLY"] = "1"
if args.export_stl: if args.export_stl:
model_ = model()
logger.info("exporting stl to %s", args.export_stl) 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: if args.export_png:
view = None model_ = model()
if "front" in args.export_svg: logger.info("exporting png to %s", args.export_png)
view = "front" export_png_image(model_, args.export_png)
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_vtk: if args.export_vtk:
vtk_file = args.export_vtk vtk_file = args.export_vtk
js_var, _ext = os.path.splitext(os.path.basename(vtk_file)) js_var, _ext = os.path.splitext(os.path.basename(vtk_file))
js_file = f'{vtk_file}.js' js_file = f'{vtk_file}.js'
model_ = model()
logger.info("exporting VTK (for web rendering) to %s", vtk_file) 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) logger.info("wrapping VTK data in a javascript variable (var %s) in %s", js_var, js_file)
vtk_data = open(vtk_file).read() vtk_data = open(vtk_file).read()