Commit Graph
50 Commits
Author SHA1 Message Date
Clifford Garwood d6de031c8a Merge remote-tracking branch 'upstream/main' into merge-test-upstream
# Conflicts:
#	src/slic3r/GUI/GCodeViewer.cpp
#	src/slic3r/GUI/GLCanvas3D.hpp
#	src/slic3r/GUI/Tab.cpp
2026-05-25 03:11:50 -04:00
SoftFever 3d250dc52c Fix crash for preset sync during startup (#13797) 2026-05-22 19:02:49 +08:00
Clifford Garwood 5fd0f3c5b7 Merge remote-tracking branch 'upstream/main' into feedback 2026-05-17 20:21:23 -04:00
Ian Bassi 3e866c4aa1 Fix build (#13654)
Remove wxInitializer fixture from tests
2026-05-13 12:31:14 -03:00
Andrew 33be9775dc Fix inconsistent displayed name (#13645)
* Add get_json_string_field helper

Introduce get_json_string_field in OrcaCloudServiceAgent.cpp to safely extract string fields from JSON objects.

* Add resolve_display_name helper

Introduce resolve_display_name to normalize provider metadata labels for the UI. The helper returns the first non-empty value from display_name, nickname, full_name, name, falling back to username, resolving human-facing label across varying provider payloads.

* Replace safe_str anonymous function

Replace get_json_string_field for better readability.

* Replace resolution flow for nickname with function

Consolidate both flows into one function for easier maintenance and more consistency.

* Update OrcaCloudServiceAgent.hpp

* Add OrcaCloudServiceAgent display name tests

Add unit tests verifying OrcaCloudServiceAgent resolves a user's display name from various session JSON shapes.
2026-05-13 17:58:08 +08:00
Clifford Garwood ab63789076 Merge remote-tracking branch 'upstream/main' into feedback
# Conflicts:
#	src/libslic3r/GCodeWriter.cpp
#	src/libslic3r/PrintApply.cpp
#	src/slic3r/GUI/Tab.cpp
#	tests/libslic3r/test_config.cpp
2026-05-13 00:57:36 -04:00
Clifford GarwoodandClaude Opus 4.7 48c603faa5 feat(imex): firmware-managed zones — center slice + ghost suppression
Adds the `imex_firmware_managed_zones` printer-config key (default off) for
IDEX/IQEX printers whose firmware applies its own copy/mirror offsets in
non-primary modes (e.g. RepRapFirmware IDEX duplication mode, Flashforge
Creator Pro 2/3 Pro). For these printers the slicer needs to emit a single
centered slice at bed origin and let the firmware fan toolheads out from there;
the previous slicer-managed iMEX rendering would draw a print at the primary
zone's world position (off-bed for the firmware-fan-out paradigm).

When the flag is on and the active mode is non-primary, the slicer subtracts
the primary zone's plate-local center from the gcode emission frame. The
writer offset is augmented but the gcode-processor offset stays at plate_origin
so the gcode-preview visualizer renders the centered slice at the bed center
rather than at the prepare-view zone placement. translate_to_print_space is
augmented too so first_layer_print_min/max placeholders (consumed by user
start_gcode like Felix's M118 header) reflect the centered frame.

Slice handoff lives in PartPlate::refresh_imex_slice_offset, called from both
update_slice_context (plate switch) and Plater::priv::update_background_process
(every-slice path — reslice() goes through here with switch_print=false so the
plate-switch hook alone wouldn't fire on mode toggle).

calc_imex_ghosts early-returns in firmware-managed mode: the existing
imex_head_transform math places ghosts at primary_zone_center + gantry_offset
(slicer-managed semantics), which renders off-bed when the toolpath is being
emitted in a centered frame. Proper firmware-managed ghost rendering (showing
where copies/mirrors will actually print after firmware fan-out) is deferred.

When the flag is off, all the new code paths reduce to no-ops byte-identical to
prior behavior. Layer 1 unit tests in test_imex_helpers cover every gating path
of compute_imex_slice_offset; full ctest suite passes (247/247).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:55:45 -04:00
dc5897d7b5 Update eigen to v5.0.1 and libigl to v2.6.0. (#11311)
* Update eigen from v3.3.7 to v5.0.1.

This updates eigen from v3.3.7 released on  December 11, 2018-12-11 to v5.0.1
released on 2025-11-11. There have be a large number of bug-fixes,
optimizations, and improvements between these releases. See the details at;

https://gitlab.com/libeigen/eigen/-/releases

It retains the previous custom minimal `CMakeLists.txt`, and adds a
README-OrcaSlicer.md that explains what version and parts of the upstream
eigen release have been included, and where the full release can be found.

* Update libigl from v2.0.0 (or older) to v2.6.0.

This updates libigl from what was probably v2.0.0 released on 2018-10-16 to
v2.6.0 released on 2025-05-15. It's possible the old version was even older
than that but there is no version indicators in the code and I ran out of
patience identifying missing changes and only went back as far as v2.0.0.

There have been a large number of bug-fixes, optimizations, and improvements
between these versions. See the following for details;

https://github.com/libigl/libigl/releases

I retained the minimal custom `CMakeLists.txt`, added `README.md` from the
libigl distribution which identifies the version, and added a
README-OrcaSlicer.md that details the version and parts that have been
included.

* Update libslic3r for libigl v2.6.0 changes.

This updates libslic3r for all changes moving to eigen v5.0.1 and libigl
v2.6.0. Despite the large number of updates to both dependencies, no changes
were required for the eigen update, and only one change was required for the
libigl update.

For libigl, `igl::Hit` was changed to a template taking the Scalar type to
use. Previously it was hard-coded to `float`, so to minimize possible impact
I've updated all places it is used from `igl::Hit` to `igl::Hit<float>`.

* Add compiler option `-DNOMINMAX` for libigl with MSVC.

MSVC by default defines `min(()` and `max()` macros that break
`std::numeric_limits<>::max()`. The upstream cmake that we don't include
adds `-DNOMINMAX` for the libigl module when compiling with MSVC, so we need
to add the same thing here.

* Fix src/libslic3r/TriangleMeshDeal.cpp for the unmodified upstream libigl.

This fixes `TriangleMeshDeal.cpp` to work with the unmodified upstream
libigl v2.6.0. loop.{h,cpp} implementation.

This file and feature was added in PR "BBS Port: Mesh Subdivision" (#12150)
which included changes to `loop.{h,cpp}` in the old version of libigl. This PR
avoids modifying the included dependencies, and uses the updated upstream
versions of those files without any modifications, which requires fixing
TriangleMeshDeal.cpp to work with them.

In particular, the modifications made to `loop.{h,cpp}` included changing the
return type from void to bool, adding additional validation checking of the
input meshes, and returning false if they failed validation. These added
checks looked unnecessary and would only have caught problems if the input
mesh was very corrupt.

To make `TriangleMeshDeal.cpp` work without this built-in checking
functionality, I removed checking/handling of any `false` return value.

There was also a hell of a lot of redundant copying and casting back and forth
between float and double, so I cleaned that up. The input and output meshs use
floats for the vertexes, and there would be no accuracy benefits from casting
to and from doubles for the simple weighted average operations done by
igl::loop(). So this just uses `Eigen:Map` to use the original input mesh
vertex data directly without requiring any copy or casting.

* Move eigen from included `deps_src` to externaly fetched `deps`.

This copys what PrusaSlicer did and moved it from an included dependency under
`deps_src` to an externaly fetched dependency under `deps`. This requires
updating some `CMakeList.txt` configs and removing the old and obsolete
`cmake/modules/FindEigen3.cmake`. The details of when this was done in
PrusaSlicer and the followup fixes are at;

* https://github.com/prusa3d/PrusaSlicer/commit/21116995d78b74dee69ce42874b643012a7c14e5
* https://github.com/prusa3d/PrusaSlicer/issues/13608
* https://github.com/prusa3d/PrusaSlicer/pull/13609
* https://github.com/prusa3d/PrusaSlicer/commit/e3c277b9eea0ca25e90e2378bcda198d56c4d304

For some reason I don't fully understand this also required fixing
`src/slic3r/GUI/GUI_App.cpp` by adding `#include <boost/nowide/cstdio.hpp>` to
fix an `error: ‘remove’ is not a member of ‘boost::nowide'`. The main thing I
don't understand is how it worked before. Note that this include is in the
PrusaSlicer version of this file, but it also significantly deviates from what
is currently in OrcaSlicer in many other ways.

* Whups... I missed adding the deps/Eigen/Eigen.cmake file...

* Tidy some whitespace indenting in CMakeLists.txt.

* Ugh... tabs indenting needing fixes.

* Change the include order of deps/Eigen.

It turns out that although Boost includes some references to Eigen, Eigen also
includes some references to Boost for supporting some of it's additional
numeric types.

I don't think it matters much since we are not using these features, but I
think technically its more correct to say Eigen depends on Boost than the
other way around, so I've re-ordered them.

* Add source for Eigen 5.0.1 download to flatpak yml config.

* Add explicit `DEPENDS dep_Boost to deps/Eigen.

I missed this before. This ensures we don't rely on include orders to make
sure Boost is installed before we configure Eigen.

* Add `DEPENDS dep_Boost dep_GMP dep_MPFR` to deps/Eigen.

It turns out Eigen can also use GMP and MPFR for multi-precision and
multi-precision-rounded numeric types if they are available.

Again, I don't think we are using these so it doesn't really matter, but it is
technically correct and ensures they are there if we ever do need them.

* Fix deps DEPENDENCY ordering for GMP, MPFR, Eigen, and CGAL.

I think this is finally correct. Apparently CGAL also optionally depends on
Eigen, so the correct dependency order from lowest to highest is GMP, MPFR, Eigen, and CGAL.

---------

Co-authored-by: Donovan Baarda <dbaarda@google.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
2026-05-12 15:09:13 +08:00
CliffordandClaude Opus 4.7 7aed2dc8bd fix(preset): don't truncate child variant vectors to parent size on load (#13316)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 16:03:39 -03:00
Clifford Garwood 493a9e96d2 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	src/libslic3r/Preset.cpp
2026-05-02 01:17:02 -04:00
SoftFever 066243afe2 Merge branch 'main' into zaa 2026-05-01 18:04:05 +08:00
SoftFever c04be9ab37 Introducing Orca Cloud: https://cloud.orcaslicer.com (#13414)
* Add OrcaCloud sync platform and preset bundle sharing system

  Introduce OrcaCloud, a cloud sync platform for user presets, alongside
  a preset bundle system that enables sharing printer/filament/process
  profiles as local exportable bundles or subscribed cloud bundles.

  OrcaCloud platform:
  - Auth to Orca Cloud
  - Encrypted token storage (file-based or system keychain)
  - User preset sync with
  - Profile migration from default/bambu folders on first login
  - Homepage integration with entrance to cloud.orcaslicer.com

  Preset bundles:
  - Local bundle import/export with bundle_structure.json metadata
  - Subscribed cloud bundles with version-based update checking
  - Thread-safe concurrent bundle access with read-write mutex
  - Canonical bundle preset naming (_local/<id>/... and _subscribed/<id>/...)
  - Bundle presets are read-only; grouped under subheaders in combo boxes
  - PresetBundleDialog with auto-sync toggle, refresh, update notifications
  - Hyperlinked bundle names to cloud bundle pages

  Co-authored-by: Sabriel Koh <sabrielkcr@gmail.com>
  Co-authored-by: Derrick <derrick992110@gmail.com>
  Co-authored-by: Mykola Nahirnyi <mnahirnyi@amcbridge.com>
  Co-authored-by: Ian Chua <iancrb00@gmail.com>
  Co-authored-by: Draginraptor <draginraptor@gmail.com>
  Co-authored-by: ExPikaPaka <112851715+ExPikaPaka@users.noreply.github.com>
  Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
  Co-authored-by: Ocraftyone <Ocraftyone@users.noreply.github.com>
  Co-authored-by: yw4z <ywsyildiz@gmail.com>
  Co-authored-by: peterm-m <101202951+peterm-m@users.noreply.github.com>

* Fixed an issue on Windows it failed to login Orca Cloud with Google account
2026-05-01 18:01:29 +08:00
Clifford GarwoodandClaude Opus 4.7 4966d0fae8 feat(imex): Span tile state for paired-gantry multicolor
Introduce ImexRole::Span as a 5th tile cycle state that declares "this
tool is the multicolor partner of Primary on the same gantry." Encoded
as the `S` role suffix in `imex_mode_active_tools` (e.g. `0:P,1:S,2:M,3:M`).
Disambiguates paired-gantry mc-mirror from 4-independent-copies — both
share the same active_tools shape sans the marker.

Span drives:
- Multicolor block rule: now requires Span on primary's gantry to allow
  multi-color slicing in a parallel mode. Replaces the prior "≥2 tools
  on primary's gantry" check; pre-existing 4-tool multicolor configs
  need T1 flipped to Span.
- Ghost aggregation: one ghost per non-primary gantry when Span is
  present, using the column-paired representative. Aggregated-mirror
  drag tracks primary 1:1 in X (gantries don't share an X rail) with
  X-flip baked into mesh-local frame so geometry still reads as mirrored.
- Zone aggregation: one full-X row strip per non-primary gantry instead
  of per-tool quadrants.
- UI: 5th button in IMEXModesCtrl. Cycle Off→P→C→M→S→Off, only offered
  on multi-gantry printers and only on tiles sharing primary's gantry row.

Single source of pairing truth: group_imex_active_tools_by_gantry in
IMEXHelpers, consumed by ghost factory and zone calculator.

Also fixes the carriage collision strip's X-boundary check, which lacked
the row constraint its Y-boundary counterpart already had — paired-gantry
mc-mirror was drawing a spurious right-edge strip from T3 sitting
diagonally from primary.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 01:16:02 -04:00
Clifford GarwoodandClaude Opus 4.7 2c604173d3 fix(imex): block multi-color slicing for single-gantry "fake IMEX" modes
Catches the case where a non-primary IMEX mode's active tools all sit on
one gantry — e.g. mode "0:P,1:C" on a 2x2 IQEX where T0 and T1 share
gantry 0. The "Copy"/"Mirror" label is decorative there: nothing actually
parallel-prints, but the user's mode_gcode still fires and emits firmware
setup that doesn't apply, while the slicer treats it as a multi-color
parallel print. Conceptually it's just a regular multi-tool single-gantry
print and belongs in Primary mode.

Changes:
- imex_multicolor_block_reason now collects the set of distinct gantries
  spanned by the active tools and short-circuits with a clear "single
  gantry — not a parallel-print scenario" message before falling through
  to the existing within-gantry-swap check.
- Drops the redundant pre-slice "Multi-material objects detected" soft
  warning from collect_imex_warnings — the slice-time block surfaces a
  more specific message at the right moment, and the soft warning was
  vague handwaving in front of it. Bed-temp + filament-type checks stay.
- New unit test covering the single-gantry block.

Behavior matrix on a 2x2 IQEX with multi-color:
  "0:P,1:C"           single gantry         -> BLOCK (new)
  "0:P,2:C"           dual gantry, 1 each   -> BLOCK (existing within-gantry-swap)
  "0:P,1:C,2:M,3:M"   dual gantry, 2 each   -> ALLOW
  multiple filaments to same physical via pem -> BLOCK (existing MMU sharing)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 22:53:33 -04:00
SoftFever 9bc2eb7476 Merge branch 'main' into zaa 2026-04-28 16:57:02 +08:00
Clifford GarwoodandClaude Opus 4.7 66891899e9 refactor(imex): drop unused Split mode-type infrastructure
The mode-type tag (imex_mode_types config + imex_mode_type_for helper +
Split sentinel) was added in 0bb1cef as scaffolding for the Split rendering
work that landed in 4370cca and then got reverted in d9be71b. With Phase 2-4
gone, this scaffolding is now unused dead code — and the design we settled
on instead is to leave topology entirely implicit (parsed from active_tools_str)
rather than carrying a per-mode type tag the user would otherwise have to
manage explicitly.

The multi-color slicing block + bare T<n> suppression that were the actual
substance of the safeguards work stay in place:
- imex_multicolor_block_reason still allows multi-color exactly when 2+ tools
  are active on the primary's gantry — Felix's hypothetical IQEX paired-gantry
  case works through this path, no new mode type required.
- Slicer-side: bare T<n> stays suppressed at print-start in IMEX parallel modes;
  mid-print T<n> emits naturally for the legitimate IQEX 4-tool-active scenario.

Removed:
- ConfigOptionStrings imex_mode_types (PrintConfig.hpp/cpp + Preset.cpp key list)
- imex_mode_type_for helper + kImexModeType{Primary,Copy,Mirror,Split} sentinels
- mode_type parameter on imex_multicolor_block_reason and the Split short-circuit
- mode_type plumbing in Print::validate and PartPlate::has_imex_multimaterial_conflict
- Three unit tests for imex_mode_type_for + two Split-specific multicolor block tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 00:48:39 -04:00
Clifford GarwoodandClaude Opus 4.7 0bb1cef78e feat(imex): polish UI per PR feedback + add parallel-mode safeguards
Felix14-v2 PR review feedback (https://github.com/OrcaSlicer/OrcaSlicer/pull/13086#issuecomment-4323696312)
plus the slice-time validation work that follows from his bug list.

UI polish:
- Capitalize "Primary" in display (right-click mode menu, plate tooltip).
  Sentinel stays lowercase for wire compatibility.
- Pre-slice-warnings checkbox now uses Orca's ::CheckBox so it matches the
  green toggle style of the rest of the IDEX/IQEX configuration page.
- DPI-scaled the IMEXModesCtrl (modes editor) sub-panels, button grid,
  text wraps, gcode textarea, and the ghost-tooltip swatch (imgui.scaled).
  Legend swatches sized to body-text height for visual balance.
- Primary mode tool buttons in the modes editor are now disabled (read-
  only): cycling roles on the IMEX-off mode is a no-op and confusing.
- Modes editor sub-panels now explicitly inherit the app's window-default
  dark colour so chromeless ScalableButtons don't render with a visible
  light box around their icons on GTK dark themes.
- Per-mode-line reset arrows in the modes editor: each row gets a small
  reset bitmap that snaps that row's name+tools+gcode triplet back to the
  saved preset's value. matches_config() guard on the page-level reload
  prevents the textbox-being-typed-into from being destroyed mid-keystroke.
- New View menu item "Show IDEX/IQEX Toolhead" — toggles the per-carriage
  footprint boxes during G-code preview playback. Gated to Preview tab +
  IMEX printer; backed by app_config so it persists.

Coordinated config migrations:
- imex_tool_layout and imex_viz_theme migrate from coString to coEnum
  (ImexToolLayout / ImexVizTheme). Existing wire format preserved so
  saved presets and 3MFs deserialize unchanged. Side-benefit: both now
  pick up standard Field rendering and so finally show reset arrows.

Slice-time safeguards (the validation half):
- imex_suppresses_bare_toolchange(parallel_mode, count): suppresses the
  slicer's bare T<n> at print-start in any IMEX parallel mode (the user's
  imex_mode_gcode + machine_start_gcode owns tool activation there). Mid-
  print T<n> emits normally — Print::validate blocks the configurations
  where mid-print T<n> wouldn't make sense. Applied to both code paths
  inside GCode::set_extruder (the long multi-extruder path AND the
  single-extruder path that fires when multiple_extruders=false).
- imex_multicolor_block_reason(): hard-stop validator returning a user-
  facing reason string when the active IMEX configuration can't physically
  support multi-color. Catches IDEX (1 tool/gantry), 2-tool-active IQEX
  (no within-gantry swap topology), and any MMU/AFC lane sharing among
  used filaments. Wired into Print::validate as a slice blocker, and into
  PartPlate::has_imex_multimaterial_conflict so the plater badge agrees
  with the slice block (no more false positives where the badge warns but
  the slice goes through).
- New imex_mode_types config option (parallel array to imex_mode_names)
  and imex_mode_type_for() helper. Mode-type tag drives behaviour: zones,
  ghosts, and validation interpret modes differently per type. Initial
  types: "primary", "copy", "mirror", "split". Split modes are explicitly
  designed for paired-gantry IQEX multi-color and bypass the gantry-pair
  check in imex_multicolor_block_reason (MMU sharing still blocks them).

Test coverage:
- New unit tests cover imex_suppresses_bare_toolchange (4 cases),
  imex_multicolor_block_reason (8 cases including IDEX, IQEX 2-/4-tool-
  active, MMU sharing, missing primary, Split type), and imex_mode_type_for
  (3 cases including legacy fallback). Total: 186 IMEX assertions across
  71 test cases, all passing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-27 22:51:05 -04:00
Clifford GarwoodandClaude Opus 4.7 41457635e9 test(imex): extract physical→logical helpers + cover them with unit tests
Three of the four IMEX physical-vs-logical fixes landed earlier on this
branch (fbc58d2a1d, fa048babeb, a38b95bf45, e11e7d46df) used inline
lambdas / direct loops to translate physical extruder indices to logical
filament slots.  No test coverage existed for the specific composition,
even though the underlying primitives (resolve_filament_for_head,
first_filament_for_physical_head) were tested.

Pull two patterns out of Plater.cpp and GCode.cpp into IMEXHelpers as
named helpers, then unit-test them:

  imex_primary_logical_from_objects(used_slots_1b, pem, primary_physical)
    Walks the plate's used filament slots (1-based) and returns the
    first one whose pem entry maps to the primary's physical extruder.
    This is what the warning's `logical_for_primary` now delegates to —
    moves the "look at object assignments, not pem first-routed default"
    behavior introduced in fa048babeb out of the lambda and into a
    separately-testable function.

  imex_secondary_logical_slots(active_physicals, primary_physical,
                               plate_head_filament_map, pem)
    Iterates IMEX active physicals, skips the one matching primary,
    resolves each remainder via resolve_filament_for_head (per-plate
    override + first-routed fallback), deduplicates, drops -1 entries.
    Replaces the inline loop in GCode::_do_export's is_extruder_used
    marking (a38b95bf45 + e11e7d46df).

10 new test cases in test_imex_helpers.cpp cover the cases that
correspond directly to bugs hit:

  imex_primary_logical_from_objects:
    - AFC primary picks the object's slot (the user's specific bug)
    - Multi-color AFC primary returns first input-order match
    - Direct extruder primary unambiguous (no MMU)
    - No object routed to primary returns -1
    - Empty inputs (no objects, empty pem)

  imex_secondary_logical_slots:
    - Copy mode skips primary, falls back to first-routed
    - IQEX 4-mode enumerates all three secondaries
    - Per-plate override wins over first-routed
    - Drops unrouted physicals + deduplicates
    - Only-primary-active returns empty

All [IMEX] + [Variant] + [3mf] regression: 166 assertions / 61 cases.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 05:07:34 -04:00
Clifford GarwoodandClaude Opus 4.7 d329fce6b0 Merge branch 'tests/imex-coverage' into feedback
Brings in the IMEX test coverage (PA per-firmware, Temperature per-firmware,
[Variant] expansion, 3MF round-trip, imex_pem_tool_for helper + tests, and
the cherry-picked variant-truncation regression test).

Resolution notes:
- Two GCode.cpp call sites for set_pressure_advance had divergent edits:
    * tests/imex-coverage rewrote them to use the new imex_pem_tool_for
      helper (commit c2492ccc47), eliminating the inline parallel-mode
      check entirely.
    * feedback replaced the literal "primary" with kImexPrimaryMode in the
      same lines (commit 085f5ccec8).
  Resolution: keep the helper-call form. The kImex change is moot on lines
  the helper replaces, and imex_pem_tool_for in IMEXHelpers.cpp is also
  updated to use kImexPrimaryMode for consistency with the rest of the
  codebase.

- Test test_3mf.cpp updated for upstream's load_bbs_3mf signature change
  (PR adds is_orca_3mf out-parameter between is_bbl_3mf and file_version).
  All three call sites in the new IMEX 3MF round-trip tests pass &is_orca
  in addition to &is_bbl.

Full regression post-merge:
  libslic3r:    143 cases / 48,553 assertions  (+10 cases from new tests)
  fff_print:     24 cases /    245 assertions  (+10 cases from new tests)
  sla_print:     21 cases / 14,100 assertions
  libnest2d:     14 cases /    488 assertions
  slic3rutils:    3 cases /      3 assertions

All tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 01:17:27 -04:00
Clifford Garwood 357fcb374d Merge remote-tracking branch 'upstream/main' into feedback 2026-04-25 00:46:48 -04:00
Clifford GarwoodandClaude Opus 4.7 ee757dac20 test: address self-review findings on [Variant] and [3mf][IMEX] coverage
Self-review found two weaknesses in the preceding test commits:

1) The equal-size [Variant] scenario claimed to distinguish the truncation
   guard's `cur > target` predicate from a regression to `cur >= target`,
   but both paths yield identical child values in practice: when
   extruder_variant names match, set_with_restore's variant_index is fully
   populated (no -1 slots) and the merge path restores every position from
   backup — producing the same {1.5, 2.5} output as the skip path. The
   test passes in both guard states.

   Rewritten to use mismatched variant names between child and parent.
   variant_index then has -1 slots, and set_with_restore overwrites those
   positions with parent values. Now the merge path yields {0.8, 0.8} and
   the skip path yields {1.5, 2.5} — observably different. Verified:
     - `cur >  target` (correct):  4 scenarios pass, 15 assertions
     - `cur >= target` (regressed): equal-size scenario fails with
       "1.5 is within 0.000000001 of 0.80000000000000004"
     - Guard removed entirely: child>parent + stride=2 both fail with
       truncation ("1 == 2" / "2 == 4")

2) The [3mf][IMEX] round-trip only covered a single plate. A plate-
   indexing regression (IMEX metadata landing on the wrong plate, or
   bleeding across plates on reload) would not have been caught.

   Added a multi-plate scenario: two plates with distinct mode and
   head-filament-map values. Asserts both land on their respective
   destination plates after reload. Load-bearing verified:
     - With IMEX serialization intact:    3 scenarios pass, 45 assertions
     - With IMEX serialization disabled:  positive + multi-plate fail
       (both "nullptr != nullptr"); primary-mode passes (expects nullptr)
     - With primary-mode short-circuit removed: primary-mode scenario
       fails ("0x... == nullptr") because primary modes now serialize

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 23:29:01 -04:00
Clifford GarwoodandClaude Opus 4.7 b45d8a5b7b test(gcode): per-firmware coverage for GCodeWriter::set_temperature(tool)
Four scenarios cover the temperature emission surface that IMEX layer-change
handling routes through (Tier 1 of the deferred Target B test plan —
pure-function-only, no fixture).

- Per-flavor command routing: Marlin (M104), RRF (G10 — M104 is deprecated
  on RRF), Mach3/Machinekit (P-prefix for value instead of S).
- Wait handling: Marlin emits M109, MakerWare/Sailfish silently drop wait
  requests (the firmware doesn't support blocking waits), Teacup and RRF
  both emit a separate M116 poll.
- Per-tool qualifier for IMEX secondary carriages: Marlin and Klipper
  emit T<N>, RRF uses P<N> (same P override as its wait poll). This is
  exactly the path that lets IMEX set secondary-tool layer temperatures
  without a tool-change.
- Instance overload's multi-extruder gating: a tool index passed to a
  single-extruder GCodeWriter is discarded (no spurious T0 on
  single-tool printers), but a multiple_extruders writer passes it
  through verbatim.

All 24 assertions in 4 cases pass under [Temperature].

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 23:08:57 -04:00
Clifford GarwoodandClaude Opus 4.7 c2492ccc47 refactor(imex): extract imex_pem_tool_for helper + unit tests
The physical_extruder_map translation used by IMEX per-tool PA emission was
inlined identically at two sites in GCode.cpp (tool-change and second-layer
transition). Extract to IMEXHelpers so the routing rule ("parallel mode AND
populated pem → physical index, else -1") is testable in isolation and the
call sites read as intent rather than re-deriving the conditional.

Production change is behavior-preserving:
- Same predicate (`!mode.empty() && mode != "primary"`)
- Same empty-pem short-circuit returning -1
- Same get_at() dispatch on hit
- Both call sites replaced with a single call

Four unit tests in [IMEX] cover the routing matrix:
  - non-IMEX ("") and primary mode short-circuit
  - parallel mode + empty pem short-circuits (defense-in-depth; get_at would
    throw on empty values otherwise)
  - identity pem (non-MMU IDEX) routes filament to itself
  - MMU collapse routes multiple logical slots to one physical (7-slot profile
    with 4-lane MMU on physical 0 and direct drives on 1/2/3)

All IMEX + Variant regression suites pass post-refactor (133 assertions / 48
cases under libslic3r, 25 assertions / 6 cases under fff_print [PressureAdvance]).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 23:07:23 -04:00
Clifford GarwoodandClaude Opus 4.7 cb15f35444 test(3mf): round-trip coverage for per-plate IMEX state
Validates that imex_parallel_mode and imex_head_filament_map survive a
full store_bbs_3mf → load_bbs_3mf cycle — the same silent-state-loss bug
class that produced the variant-vector truncation regression, applied to
IMEX plate state which rides the same XML metadata path.

- Positive round-trip: a plate with copy_mode + a non-trivial head
  filament map ("1:2,2:3") is saved and reloaded; both options land on
  the destination plate's config with the exact values preserved.
- Guard scope: a plate with mode="primary" and empty head-filament-map
  does NOT emit metadata (per the serializer's short-circuit), and the
  reload leaves both options absent from the destination config. If the
  serializer ever regressed to writing primary-mode plates, the load
  path would surface phantom "primary" strings on plates that shipped
  clean — this catches that.

Both scenarios call set_temporary_dir to point the BBS exporter's backup
scaffolding at a writable per-process temp directory (by default it
resolves under root at runtime, which fails for non-root test
processes).

All 27 assertions in 2 test cases pass under [3mf][IMEX].

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 22:58:19 -04:00
Clifford GarwoodandClaude Opus 4.7 5434a5217c test(gcode): per-firmware coverage for GCodeWriter::set_pressure_advance(tool)
Exercises the IMEX per-tool PA emission surface added in af59501f4a
("feat: firmware-agnostic per-tool PA emission for IMEX parallel modes").
Six scenarios cover the full routing matrix:

- Negative PA returns empty across all flavors (early-exit guard).
- Klipper: bare vs EXTRUDER=extruder vs EXTRUDER=extruderN. Asserts the
  tool=0 case emits the unsuffixed extruder name (first Klipper extruder
  is named "extruder", not "extruder0") — a subtle edge case easy to
  regress.
- RRF: bare vs D0 vs DN. The D0 case matters: passing tool=0 explicitly
  must emit `D0`, not the current-tool fallback.
- Marlin 2.x: bare vs T0 vs TN.
- Marlin Legacy: tool index is silently dropped — verifies the fallback
  branch can't accidentally start emitting T qualifiers on firmware that
  doesn't support them.
- BBL: flag wins over firmware flavor (Marlin 2 flavor + BBL flag emits
  the BBL-specific `M900 K... L1000 M10`) and BBL never emits a per-tool
  qualifier regardless of the tool argument.

All 25 assertions across 6 cases pass under [PressureAdvance].

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 22:53:24 -04:00
Clifford GarwoodandClaude Opus 4.7 af8fe649ef test(preset): expand [Variant] coverage — stride=2, equal-size, non-variant guard
Adds three scenarios alongside the existing child>parent stride=1 regression
test for update_non_diff_values_to_base_config:

- stride=2 child>parent: machine_max_acceleration_x (size 4 vs 2) — confirms
  the truncation guard fires for the (normal,silent)-pair stride=2 path, not
  just stride=1. Catches a regression class the existing test would miss
  because stride=2 routes through normalize_stride2_floats and a different
  set_with_restore call site.

- equal-size (2=2): exercises the path the guard does NOT short-circuit;
  asserts child per-extruder values survive set_with_restore's nil-restore
  merge. Catches any future change that breaks the equal-size merge — the
  fix's `cur > target ? skip` predicate could regress to `cur >= target` and
  silently override child values otherwise.

- non-variant scalar: layer_height in `keys` and `different_keys` but absent
  from printer_options_with_variant_1/_2. Hits the is_scalar() / "nothing to
  do" branch and must remain untouched. Scopes the guard's blast radius.

All four scenarios in the [Variant] tag pass: 15 assertions, 4 test cases.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 22:49:59 -04:00
Clifford GarwoodandClaude Opus 4.7 6ed688dfc5 test(preset): regression test for child>parent variant-vector truncation
Adds a Catch2 scenario that builds a 2-extruder child DynamicPrintConfig
inheriting from a 1-extruder parent, calls update_non_diff_values_to_base_config
through the real printer_options_with_variant_1 / _2 key sets, and asserts
that printer_extruder_id, printer_extruder_variant, and retraction_length
retain their full size after the merge. Covers three distinct
set_with_restore<T> instantiations (Ints, Strings, Floats) and verifies
both size preservation and per-extruder value preservation.

Verified load-bearing: with the guard in update_non_diff_values_to_base_config
temporarily removed, the test fails with "1 == 2" on pe_id.values.size() and
retraction_length.values.size(); with the guard restored, all six assertions
pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 20:42:57 -04:00
Wachhund SkytowerandClaude Opus 4.6 1eb9a8efbd Fix Windows test linking: use main() instead of wmain() (#12939)
wxWidgets defines _UNICODE globally, which causes Catch2's
catch_main.cpp to provide wmain() instead of main(). This leads to
LNK2001 "unresolved external symbol main" for all test executables
when building with BUILD_TESTS=ON on MSVC.

Add DO_NOT_USE_WMAIN compile definition to Catch2WithMain target
so that Catch2 provides the standard main() entry point.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 14:07:24 +08:00
Clifford GarwoodandClaude Opus 4.7 9a87b96ded refactor(imex): Mirror reflects about zone-boundary plane, not primary origin
Replace imex_head_transform's fifth argument (Vec3d primary_origin) with a
Vec2d primary_zone_center and rewrite the Mirror branch as a true reflection
about the plane x = primary_zone_center.x + gantry_offset.x/2. Previous math
flipped about the primary's current origin, which:
  * let the ghost drift out of the target zone as the primary moved, and
  * made mirrored drag motion track 1:1 with the primary instead of reflecting.

The new transform places the ghost at the mirrored position within the target
zone (matching where the mirror tool actually prints) and reflects drag so
primary +X → ghost -X while Y tracks 1:1 — i.e. the ghost stays a true
mirror while the user drags. Off-row Mirror targets (e.g. T3 on a 2x2) still
reflect across the same X-plane as on-row peers.

PartPlate::calc_imex_ghosts and update_imex_ghost_transforms now feed primary_off
(the primary head's zone center) instead of an instance-space Vec3d.

Mirror tests rewritten against the new geometric contract: ghost origin at the
reflected position, primary drag deltas reflected across the zone-boundary plane.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 22:51:56 -04:00
Clifford GarwoodandClaude Opus 4.7 6a3de6a28f feat(imex): effective_physical_extruder_map helper + diagnostic no-filament tooltip
Centralize the project→printer→printer_extruder_id fallback for the physical
extruder map. PrintApply, PartPlate (ghost color + cache key), Plater (tooltip
+ click gate) all previously open-coded the three-step lookup, and each handled
the "pem unset, derive from pei" case slightly differently — an IDEX printer
without an explicit pem could paint an UNPRINTABLE_COLOR ghost even though the
slicer would have derived a valid mapping.

- IMEXHelpers: add effective_physical_extruder_map(explicit_pem, pei) and a
  PresetBundle overload that wraps the project→printer precedence.
- PrintApply: use the helper in place of the inline pei→pem normalization.
- PartPlate / Plater: call the PresetBundle overload at every ghost-color,
  ghost-cache-key, tooltip, and click-gate site.
- Plater::format_imex_ghost_tooltip: when no filament resolves to a head,
  surface an actionable message directing the user to extend the extruder
  count in the Machine tab, instead of the generic "(no filament routed)".
- IMEXFilamentPickerPopover: hold m_pem by value so callers can pass a
  stack-local derived pem without lifetime worries.
- Tests: 5 new cases covering explicit-wins, default-pem fallback, null
  inputs, and the IDEX ghost-color regression that motivated this.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 22:51:31 -04:00
Clifford Garwood 77c32a2e15 feat(imex): plate ghost renderer + per-plate filament map
Replaces the plater-icon popover with colored transparent ghost copies
of primary-head instances on the plate, one per secondary active head
under its Copy/Mirror role transform. Left-click on a ghost opens a
compact filament picker popover for the ghost's head (MMU lane override).
Ghosts track the primary through drag/rotate/scale/mirror and invalidate
on mode or pem changes.

Key pieces:
  IMEXHelpers -- imex_head_transform (Primary/Copy/Mirror), shared role
    parser, per-head filament resolution with X-axis Mirror anchor.
  PartPlate -- ghost state, volume rebuild on mode/map/object mutation,
    primary_origin plumbed for Mirror reflection across the primary-row
    gantry plane.
  GLCanvas3D -- ghost rendering with per-head filament color and
    translucent blending; picking routed via volume composite id.
  Plater -- ghost click + tooltip; plater icon left-click always cycles.
  IMEXFilamentPickerPopover -- BitmapComboBox row for one secondary head,
    writes imex_head_filament_map on selection.
  bbs_3mf -- round-trip the per-plate imex_head_filament_map option.
  PrintConfig -- add imex_head_filament_map as a plate option.

MMU/AFC routing for parallel modes relies on the printer profile's
physical_extruder_map (see prior commit for authoring format). Primary-
row heads and their per-plate filament overrides are resolved through
that map, so PA and temperature emission address the correct physical
extruder when multiple logical slots share one carriage.

Tests: IMEXHelpers coverage for Primary/Copy/Mirror transforms
including a 2x2 off-row regression guard for the X-axis reflection fix.
2026-04-21 14:56:22 -04:00
Aleksandr Dobkin e8357f60d5 Fix ZAA test failure in test_extrusion_entity.cpp 2026-03-11 00:28:14 -07:00
SoftFever 9703a6b4d7 init 2026-01-23 17:05:56 +08:00
luzpazandIan Bassi a036de042b Fix various typos in source documentation (#11553)
* Fix various typos in source documentation

* Delete cmake/modules/Catch2/CatchAddTests.cmake

* Delete tests/example/example_tests_main.cpp

* Revert test_config.cpp

---------

Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
2026-01-21 09:19:25 -03:00
SoftFever 5f18efa9e2 Merge branch 'main' into feat/configurable-bambu-network-lib 2025-12-27 23:40:35 +08:00
NoisyfoxandSoftFever 0aac0478e7 GCode Macro: Fix placeholder parser bugs and enable tests (#11485)
* Support creating vector variable

* Add tests for placeholder parser variables

* Fix placeholder line width substitution & tests

* Enable PlaceholderParser tests

* fix build errors

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2025-12-23 23:44:43 +08:00
Maciej Wilczyński 0df673b0d3 Implement support for loading custom plugin binaries 2025-12-14 16:05:55 +01:00
Maciej Wilczyński a4d4bfff27 Allow selecting specific network plugin versions 2025-12-14 14:26:16 +01:00
coryrcandSoftFever 52c2a85d28 Fix tests (#10906)
* Get libslic3r tests closer to passing

I can't get geometry tests to do anything useful. I've added extra
output, but it hasn't helped me figure out why they don't work
yet. That's also probably the last broken 3mf test doesn't work.

The config tests were mostly broken because of config name changes.

The placeholder_parser tests have some things that may-or-may-not
still apply to Orca.

* Vendor a 3.x version of Catch2

Everything is surely broken at this point.

* Allow building tests separately from Orca with build_linux.sh

* Remove unnecessary log message screwing up ctest

Same solution as Prusaslicer

* Make 2 TriangleMesh methods const

Since they can be.

* Move method comment to the header where it belongsc

* Add indirectly-included header directly

Transform3d IIRC

* libslic3r tests converted to Catch2 v3

Still has 3 failing tests, but builds and runs.

* Disable 2D convex hull test and comment what I've learned

Not sure the best way to solve this yet.

* Add diff compare method for DynamicConfig

Help the unit test report errors better.

* Perl no longer used, remove comment line

* Clang-format Config.?pp

So difficult to work with ATM

* Remove cpp17 unit tests

Who gives a shit

* Don't need explicit "example" test

We have lots of tests to serve as examples.

* Leave breadcrumb to enable sla_print tests

* Fix serialization of DynamicConfig

Add comments to test, because these code paths might not be even used
anymore.

* Update run_unit_tests to run all the tests

By the time I'm done with the PR all tests will either excluded by
default or passing, so just do all.

* Update how-to-test now that build_linux.sh builds tests separately

* Update cmake regenerate instructions

Read this online; hopefully works.

* Enable slic3rutils test with Catch2 v3

* Port libnest2d and fff_print to Catch2 v3

They build. Many failing.

* Add slightly more info to Objects not fit on bed exception

* Disable failing fff_print tests from running

They're mostly failing for "objects don't fit on bed" for an
infinite-sized bed. Given infinite bed is probably only used in tests,
it probably was incidentally broken long ago.

* Must checkout tests directory in GH Actions

So we get the test data

* Missed a failing fff_print test

* Disable (most/all) broken libnest2d tests

Trying all, not checking yet though

* Fix Polygon convex/concave detection tests

Document the implementation too. Reorganize the tests to be cleaner.

* Update the test script to run tests in parallel

* Get sla_print tests to build

Probably not passing

* Don't cause full project rebuild when updating test CMakeLists.txts

* Revert "Clang-format Config.?pp"

This reverts commit 771e4c0ad2.

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2025-12-08 22:42:11 +08:00
Noisyfox 416b447ab0 Fix compile 2025-11-14 15:05:27 +08:00
Nanashi ebb89a583d Fix httpbin.org 503 by switching to maintained httpbingo.org (#11250) 2025-11-03 23:57:24 +08:00
Noisyfox 99863163b2 Fix unit tests (#11199)
* Fix tests build issue on Windows

* Fix `Http digest authentication` 404 error

* Fix `libnest2d_tests` missing dlls on Windows
2025-10-30 14:36:24 +08:00
coryrcandSoftFever 275f3a7f1e Build and run a test in CI (#10835)
* Actually build tests on Linux and allow RelWithDebInfo

They weren't being built.

Also cleaned up --config flags which enables RelWithDebInfo on Linux,
now that Ninja Multi-Config is used, it's quite trivial.

* Remove obsolete Slic3r Perl tests

The directory doesn't exist, they're already gone.

* Add GH job for running unit tests

* Move unit test execution to script and upload test results

* Don't run scheduled builds on forks

* Only deploy from SoftFever/OrcaSlicer

Will stop failures on forks

* Use artifact instead of cache

* Tweak archive and checkout paths

Keep getting error:

```
/home/runner/work/_temp/902d0a0a-6d23-4fe0-a643-8b5cc4efd25b.sh: line 1: scripts/run_unit_tests.sh: Permission denied
```

That seems to be because I didn't use actions/checkout, the working
directory is never setup correctly? So using checkout to get scripts
directory. Unsure if archive will preserve the `build/tests/` prefix;
will find out soon.

* Use tar to package directory and write results to correct directory

Tar preserves filenames and directory structure

* Use tar -xvf not -xzf

Muscle memory failed me

* Add testing wiki page

* Save test logs on failure and choose correct directory for junit

* Consolidate apt install steps, use for unit tests too, disable non-Linux builds

Temporarily disable non-Linux builds to save time while developing
this.

Cache the apt packages to save some time searching apt and downloading
them again (though I realize this is also downloading, but hopefully
by something closer and faster).

Remove all the redundant packages listed in the workflow and debian
distribution lists.

* Remove apt install steps from workflow

`./build-linux.sh -u` is supposed to install all needed packages, so
it should build without needing anything besides that. If I'm wrong
this commit will be dropped.

* Need composite action checked out locally

* Re-enable non-Linux builds now that it's working

* Skip a deploy and a notarize in forks

They only succeed in the main repo.

* Fix multi-build for non-Release builds: share CONFIG

* Correct build errors in unit tests

Indeterminate method signatures resolved. Updated script to build all
the tests.

* Fix -g vs -e for RelWithDebInfo

* Change CONFIG->BUILD_CONFIG

Missed one in prior commits

* Reduce wasteful redundant build artifact copies

1. Don't copy the artifacts and leave them; make a hard link first;
only make a copy only while creating AppImage.

2. Don't tar up the `package` directory; nothing uses this tar AFAICT

* Fix directory name

* Change jigsaw auth test URLs to httpbin.org

No idea why the basic auth doesn't work, but it doesn't work for
`curl` CLI either. This does.

* Remove force-build

It got reverted at
https://github.com/SoftFever/OrcaSlicer/commit/e3f049829bff3ac4de9fd271768948efc150e4c3
for unknown reasons.

* Add timeout for unit tests in GitHub Actions workflow (#11146)

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
2025-10-29 20:56:06 +08:00
2a3e761ab9 Optimize and simplify MarchingSquares.hpp. (#10747)
* Optimize and simplify MarchingSquares.hpp, and fix it's test.

This changes the implementation to get the possible next directions for a cell
when building the tags and clearing them as the cells are visited during the
march, instead of adding the visited previous direction to the tags during the
march. The Dir enum has been turned into bit flags that for the possible next
directions with boolean operators for testing/setting/clearing them. This
simplifies and optimizes many operations during the march and building the
polygons.

The complicated/broken and unused partial support for cell overlap has been
removed, simplifying the overly confusing grid iteration logic.

The broken test has been fixed by removing the now gone `RasterBase` namespace
from `sla::RasterBase::Pixeldim` and `sla:RasterBase:Resolution`, and the
CMakeLists.txt entry uncommented.

make Dir into flags

* Further optimize MarchingSquares.hpp and improve comments.

* Switch from a single byte-vector containing tags and dirs for each cell to a
  m_tags vector of bit-packed tags for each grid corner and an m_dirs vector
  of packed 4bit dirs for each cell. Since each grid corner tag is shared by
  the 4 adjacent cells this significantly reduces storage space and avoids
  redundantly calculating each tag 4x. It also significantly improves memory
  locality with each phase of calculating tags, calculating dirs, calculating
  rings operating only on the tags or dirs data required without them being
  interleaved with the data they don't need.

* Change NEXT_CCW to be initialized with a static constexpr lambda instead of
  a manually entered table. This avoids typo errors manually building the
  table.

* Optimize search_start_cell() so it can efficiently skip over cleared blocks
  of 8 dirs in the packed m_dirs vector.

* Change the tags logical labeling to better suit the packed tags vector data.
  This makes it a tiny bit more efficient to extract from the m_tags bitmap.

* Remove the now unused SquareTag enum class.

* Add comments explaining the algorithm, including corner-cases in cell
  iteration.

* Remove unused Dir operators and get_dirs() argument, and clang-format.

* Fix some bugs and add stream output operators for debugging.

* Fix a bug building tags where `step(gcrd, Dir::right)` was not assigned to
  update the gcrd grid point. Perhaps this should be a mutating method, or
  even a += operator? Also when wrapping at the end of a row it was updating
  the gcrd grid point by mutating the p raster point instead of itself.
  Perhaps Grid and Raster points should be different types? Maybe even
  templated?

* Fix a bug in get_tags() when the second row tags are packed into any of the
  2 LSB's of the uint32_t blocks. In hind-sight obviously `>>(o - 2)` will not
  shift left when `o < 2`.

* Move interpolation of the edge-crossings into a `interpolate()` method, and
  make it shift bottom and right side points "out" by one to account for
  raster pixel width. This makes the results track the raster shapes much more
  accurately for very small windows.

* Make `interpolate_rings()` check for and remove duplicated points. It turns
  out it's pretty common that two edge-crossing-points at a corner interpolate
  to the same point. This can also happen for the first and last points.

* For Coord add `==` and `!=` operators, and use them wherever Coord's are
  compared.

* Add `<<` stream output operators for Coord, Ring, and Dir classes. Add
  `streamtags(<stream>)` and `streamdirs(<stream>)` methods for dumping the
  tags and dirs data in an easy to understand text format. These make
  print-debugging much easier.

* Add `assert(idx < m_gridlen)` in a bunch of places where grid-indexes are
  used.

* For test_clipper_utils.cpp fix three "ambiguous overloading" compiler errors.

This just adds three `Polygons` qualifications to fix compiler errors about
ambiguous overloaded methods.

Note this file was formated with a mixture of tabs and spaces and had lots of
trailing whitespace. My editor cleaned these up resulting in a large looking
diff, but if you use `git diff -w` to ignore the whitespace changes you will
see it is actually tiny.

errros

* Update SLA/RasterToPolygons.* for MarchingSquares.hpp improvements.

Change the minimum and default window size from 2x2 to 1x1. Also remove the
strange pixel size re-scaling by (resolution/resolution-1).

The old MarchingSquares implementation had complications around a default
minimum 1 pixel "overlap" between cells which messed with the scaling a tiny
bit and meant when you requested a 2x2 window size it actually used a 1x1
window. Both of these meant you had to specify a window 1 pixel larger than
you really wanted, and you needed to undo the strange scaling artifact for
accurate dimensions of your results.

This has been fixed/removed in the new implementation, so the window is the
window, there is no overlap, and no strange miss-scaling.

* Fix test_marchingsquares.cpp and add StreamUtils.hpp.

This fixes the MarchingSquares unittests to both pass and be more strict than
they were before.

It also adds libslic3r/StreamUtils.hpp which includes some handy streaming
operators for standard libslic3r classes used to show extracted polys in the
unittests.

* Change Format/SL1.cpp to support the min 1x1 window for MarchingSquares.

* Fix the ring-walk termination condition.

Terminate the ring-walk when we return to the starting cell instead of when we
reach a cell with no remaining directions. This ensures we don't merge two
polygons if we started on an ambiguous cell.

* Revert the removal of duplicate points in interpolate_rings().

It turns out that duplicate points are only relatively common when using a 1x1
window. These happen when the line passes through the corner pixel on a
top-left corner in the raster, and the probability of this rapidly declines as
the window increases, so in many cases this filtering is just overhead. It can
also be potentially useful to see the points for every edge crossing even if
they are duplicates. This kind of filtering is already done and done better in
the polygon post-processing.

* rename `interpolate()` to `interpolate_edge()`, make it update the point
  in-place, and add asserts to ensure the input point is a valid edge
  interpolation point.
* Remove the duplicate point filtering from `interpolate_rings()` and simplify
  it.

* Optimize directions building.

This optimizes `get_dirs_block8()` to rapidly skip over blocks where the tags
produce no directions (all tags are 1's or 0's), and also to build the
directions faster when it has to by fetching the whole blocks worth of tags at
once instead of cell-by-cell.

* Rename `get_tags()` to `get_tags9()` and make it fetch a row of nine tags
  instead of the tags for a single cell.

* Optimize `get_dirs_block8()` to use `get_tags9()` to get the next nine tags
  for the current and next rows and then shift through them to generate the
  tags and directions for each cell in the block. Also abort early and just
  return an empty block if the tags are all 0's or all 1's.

* Tiny optimization for `get_tags_block32()`.

This avoids using the `step()` method for a simple step-right that can be done
with a simple increment of the column. It also avoids re-calculating the
raster-coodinates for every corner, instead incrementing the column by
`m_window.c` until the end of a row.

* Fix svg output in test_marchingsquares.cpp for recreate_object_from_rasters.

These SVG's were not properly centered...

* Fix 2 static_casts for compiling on Windows.

Thanks to RF47 for pointing this out on the #10747 pull request.

* Make edge iteration use O(ln(N)) binary search instead of linear.

This should be much faster when the window size is large.

* Make `CellIt` into a `std::random_access_iterator_tag` so that
`std::lower_bound()` can use a binary search to find the point on the edge
instead of a linear search.

* Change `step()` to support an optional distance argument and make it modify
the `Coord` in-place instead of return a new one.

* Update tests for the `step()` change.

* Add Catch2 BENCHMARK tests for MarchingSquares.

This required enabling the benchmarks in the tests/CMakeLists.txt config.

* Add a _Loop<> specialization for parallel execution using ExecutionTBB.

This is something that could be added wherever you are going to use this, but
I intend on using this in multiple places so we might as add this once in one
place where it can be reused.

* Fix whitespace in messed up by tab-replacements.

My editor renders, and replaces, tabs as 8 spaces. This messed up the
indenting in tests/libslic3r/CMakeLists.txt and
tests/libslic3r/test_clipper_utils.cpp when I made tiny changes in them.
This fixes the indenting using 4 chars. Note it will still show as a diff
because it is replacing tabs with 4 spaces, and removing trailing whitespace.

But at least it's now indented correctly...

---------

Co-authored-by: Donovan Baarda <dbaarda@google.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
2025-10-19 19:27:55 +08:00
SoftFever 71fd381c3c Fix tests build errors on Mac 2025-08-25 19:19:31 +08:00
SoftFever b16a6052cb Feature/re enable tests (#10503)
* re-enable tests

* Add comprehensive testing guide for OrcaSlicer in CLAUDE.md

* fix build errors on Win

* fix appimage errors
2025-08-24 20:58:18 +08:00
SoftFeverandMerill 9b2c2bff1d Support larger printer sizes by using 64-bit.
SuperSlicer is referenced for some changes.

Co-authored-by: Merill <merill@free.fr>
2024-05-10 23:47:08 +08:00
Vojtech Bubnik 05194ab1f4 PlaceholderParser: new interpolate_table() "function"
interpolate_table(x, (x0, y0), (x1, y1), (x2, y2), ...)
interpolates a table at position x.
2023-08-30 23:37:30 +08:00
SoftFever 37c54aa4f6 clean up 2023-08-09 13:42:41 +08:00
lane.wei 1555904bef Add the full source of BambuStudio
using version 1.0.10
2022-07-15 23:42:08 +08:00