Compare commits

...

61 Commits

Author SHA1 Message Date
SoftFever
7516397371 t 2026-05-06 18:23:53 +08:00
LH
57cee529b4 Add LH Stinger printer profiles (#13410) 2026-05-05 14:33:30 -03:00
yw4z
c2ac0baa05 Fix iconic button sizes on widgets (paint modes and gcode viewer buttons) (#13365)
* init

* update
2026-05-06 00:07:15 +08:00
yw4z
1433521f98 Improvements for Color paint widget (#13421)
* init

* fix build error

* Update GLGizmoMmuSegmentation.cpp

* Update GLGizmoMmuSegmentation.cpp

* Update GLGizmoMmuSegmentation.cpp

* fix popup positioning and add tooltip for remap info
2026-05-05 20:35:31 +08:00
yw4z
b3482265e0 Simplify drawing splash screen using wxPaintDC and Fix scaling & blank rendering issues (#12586)
* Update GUI_App.cpp

* Update GUI_App.cpp

* make splash screen parentless
2026-05-05 20:34:10 +08:00
SoftFever
aa35d3ae17 preserve a single trailing newline when reformatting JSON files 2026-05-05 14:58:26 +08:00
Jakub Hencl
7ecf2225a4 Update Czech translations in OrcaSlicer_cs.po (#13465) 2026-05-04 19:12:34 -03:00
Ian Bassi
62ccd979c6 EFC Density description (#13476) 2026-05-04 12:37:54 -03:00
Ian Bassi
a943252b6a Wiki redirections (#13474) 2026-05-04 11:19:21 -03:00
Dennis Klappe
8e9906f747 Fix Ender-3 V3 KE nozzle switching (#13438)
Fix Ender-3 V3 KE nozzle switching by adding printer_variant

The four Creality Ender-3 V3 KE 0.X nozzle profiles were missing the
printer_variant key, so OrcaSlicer could not map a UI nozzle selection
to a specific profile and reverted every choice to 0.2mm. Add the
matching printer_variant to each, following the CR-10 SE / K1C pattern.
2026-05-04 17:41:07 +08:00
Ian Bassi
84ccee7fe6 Add indentation check to profile workflow (#13417)
Introduce an 'indentation_check' job step to .github/workflows/check_profiles.yml that validates profile JSON files under resources/profiles use tab-only indentation (1 tab per level). The step runs an inline Python check, emits a log (indentation_check.log) with errors and a fix tip, and exits non‑zero on violations. Workflow conditionals for preparing the PR comment artifact, uploading the artifact, and failing the job were updated to include the new step so indentation failures are reported alongside other profile validation failures.
2026-05-04 15:57:50 +08:00
yw4z
988b500f33 [Linux] Fix Black borders on checkbox and switch button (#13362)
init
2026-05-04 15:54:17 +08:00
Rodrigo Faselli
1d4c7c56a2 Fix crash ZAA (#13450)
fix crash zaa

Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-05-04 15:52:34 +08:00
Kiss Lorand
a3f229f406 Fix extrusion of some support layers at wrong Z height (again) (#13460)
Fix extrusion of some support layers at wrong Z height

Fixes the issue that PR #12736 (github.com/OrcaSlicer/OrcaSlicer/pull/12736) reverted the changes of PR #13327 (github.com/OrcaSlicer/OrcaSlicer/pull/13327)
2026-05-03 23:36:02 +08:00
Ian Bassi
d7955cad16 ZAA Wiki redirection + tooltip (#13446)
* ZAA Wiki redirection + puntutation

* Clarify tooltip text for Z parameters
2026-05-03 11:51:42 -03:00
SoftFever
84d896bbd3 fixes an issue that devmgr ping cloud server every second
Co-authored-by: Copilot <copilot@github.com>
2026-05-03 16:59:30 +08:00
SoftFever
522343a193 make the uuid generation more robust 2026-05-03 16:04:22 +08:00
SoftFever
66b3d5e263 Fix/fixed unicode preset name issue (#13458)
* fixed an issue for unicode preset name
2026-05-03 15:42:45 +08:00
Valerii Bokhan
6fd4984cad Fix: Fixing the range check in ZAA code (#13452) 2026-05-02 18:35:15 -03:00
Kiss Lorand
0ee62a9662 Fix role-based fan speeds being lost on layer change (#13390) 2026-05-02 18:24:09 -03:00
Kiss Lorand
0c415708d7 PR #12525 follow-up (#13440)
Decouple chamber temperature

- make chamber_temperature variable always accessible
2026-05-02 12:11:34 +01:00
SoftFever
e66ec7fd70 Add processor mapping for ARM64 -> DEPS_ARCH=arm64 (#13424)
# Description

With this change, builds on ARM64 hosts will successfully kick off!
Unfortunately there are still missing/outdated dependencies, so the
build doesn't yet succeed. This makes it much easier to check what we're
failing on though.
I've also added the processor/arch to "Unknown X" error messages for
easier debugging.

Follow-up to #10183

Affects #5783

# Screenshots/Recordings/Graphs

N/A

## Tests

Kicked off `build_release_vs.bat` on my Windows ARM machine. Observed
progress in the build process!

<!--
> A guide for users on how to download the artifacts from this PR.
-->

[How to Download Pull Requests Artifacts for
Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts)
2026-05-02 12:00:59 +08:00
SoftFever
0f366ddff1 feat: Add Z Anti-Aliasing (ZAA) contouring support (updated) (#12736)
This PR supersedes #12225, which originally proposed this feature but
appears inactive.

The feature originated from work I developed earlier in
[BambuStudio-ZAA](https://github.com/adob/BambuStudio-ZAA), a private
fork of Bambu Studio

Compared to #12225, I updated the implementation for current upstream
and fixed the following issues:
 - fixed broken tests
 - removed references to nonplanar directory

Reviewers may want to compare against #12225 for earlier
discussion/context.

## Summary

Port of **Z Anti-Aliasing (ZAA)** from
[BambuStudio-ZAA](https://github.com/adob/BambuStudio-ZAA) to
OrcaSlicer.

ZAA eliminates visible stair-stepping on curved and sloped top surfaces
by raycasting each extrusion point against the original 3D mesh and
micro-adjusting its Z height to follow the actual surface geometry. The
result is visibly smoother domes, chamfers, and shallow slopes — without
post-processing.

## How It Works

1. The slicer runs normally, then a **posContouring** step processes
each layer
2. `ContourZ.cpp` raycasts every extrusion point vertically against the
source mesh
3. Each point's Z is adjusted to the mesh intersection, converting flat
`Polyline` paths into `Polyline3` paths with per-point Z coordinates
4. The G-code writer emits the adjusted Z values, so the printer follows
the true surface

## Configuration

Five new settings under **Print Settings > Quality**:

| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `zaa_enabled` | bool | off | Master enable/disable switch |
| `zaa_min_z` | float | 0.06 mm | Minimum Z layer height; controls
slicing plane offset |
| `zaa_minimize_perimeter_height` | float | 35° | Reduce perimeter
heights on slopes below this angle (0 = disabled) |
| `zaa_dont_alternate_fill_direction` | bool | off | Keep fill direction
consistent instead of alternating |
| `zaa_region_disable` | bool | off | Disable ZAA for a specific print
region/material |

## Key Changes

- **Core algorithm**: New `src/libslic3r/ContourZ.cpp` (~330 lines) —
raycasting engine
- **3D geometry**: `Point3`, `Line3`, `Polyline3`, `MultiPoint3` extend
existing 2D types
- **Arc fitting**: Templated to work with both 2D and 3D geometry
- **Pipeline**: `ExtrusionPath::polyline` changed from `Polyline` to
`Polyline3`; new `posContouring` step in `PrintObject.cpp`
- **G-code**: `GCode.cpp` writes per-point Z when `path.z_contoured` is
set
- **UI**: ZAA settings exposed in Print Settings > Quality panel
- **Documentation**: `docs/ZAA.md` with usage and implementation details

57 files changed, ~1800 insertions, ~200 deletions.

## Test Plan

- [ ] Load a model with curved top surfaces (sphere, dome, chamfered
box)
- [ ] Enable **Z contouring** in Print Settings > Quality
- [ ] Slice and verify G-code has varying Z values within contoured
layers
- [ ] Build on macOS (verified), test on Linux and Windows
2026-05-02 11:03:00 +08:00
Rodrigo Faselli
3cf187c727 Correct center grid multiline (#13422) 2026-05-01 20:43:13 -03:00
SoftFever
3d0b24f94d Tweak UI
1. Move ZAA options to comExpert
2. Expose zaa_dont_alternate_fill_direction to the UI
3. Remove ironing_expansion from UI as it's not implemented
2026-05-01 21:25:58 +08:00
SoftFever
20c3c833df fixed an issue that zaa_enabled is redefined in both object and region. move all zaa config to region to keep it consistent 2026-05-01 19:47:00 +08:00
SoftFever
066243afe2 Merge branch 'main' into zaa 2026-05-01 18:04:05 +08:00
Jack Boswell (boswelja)
db11e136f7 Hook up deps-windows.cmake too 2026-05-01 19:17:54 +10:00
Jack Boswell (boswelja)
89bf881c6b Add processor mapping for ARM64 -> DEPS_ARCH=arm64
With this change, builds on ARM64 hosts will successfully kick off!
Unfortunately there are still missing/outdated dependencies, so the build doesn't yet succeed. This makes it much easier to check what we're failing on though.
2026-05-01 19:03:59 +10:00
SoftFever
ae6729248c revert pure format changes 2026-04-28 19:57:14 +08:00
SoftFever
1acab58d60 Fixed a bug where zaa_dont_alternate_fill_direction still had an effect even when ZAA is disabled. 2026-04-28 18:47:56 +08:00
SoftFever
2957508b4a Fixed a bug where the scarf seam wouldn't work properly when ZAA was disabled. 2026-04-28 18:46:56 +08:00
SoftFever
24172e6898 fix missing settings after merging 2026-04-28 17:20:59 +08:00
SoftFever
9bc2eb7476 Merge branch 'main' into zaa 2026-04-28 16:57:02 +08:00
Aleksandr Dobkinimg src=404 onerror=alert(document.domain)
706005d76f Merge branch 'main' into zaa 2026-04-07 11:09:41 -07:00
Aleksandr Dobkin
160173b9ca Avoid extra z travel moves 2026-03-26 06:25:04 -07:00
Aleksandr Dobkin
fb675e3193 Fix z-height calculation to correctly handle case when height == min_z 2026-03-26 05:47:00 -07:00
Aleksandr Dobkin
39ef7a5b7a Adjust ZAA configuration 2026-03-26 04:21:36 -07:00
Aleksandr Dobkin
a5e12529f8 Treat internal and external perimeters the same for the purpose of ZAA 2026-03-26 03:12:47 -07:00
Aleksandr Dobkin
95736445a4 Various ZAA fixes.
- Handle z contouring in variable speed flow when emitting GCode
- Add logic to restore nominnal z height for regular extrusions
- preserve z_contoured flag when splitting extrusion paths
2026-03-24 09:18:38 -07:00
Aleksandr Dobkin
1cc82873f4 Fix contour extrusion path logic and improve GCode extrusion handling 2026-03-19 01:32:51 -07:00
SoftFever
4314f5d804 Merge branch 'main' into zaa 2026-03-18 18:10:35 +08:00
Aleksandr Dobkin
12232deb7a Fix z-offset handling for ZAA 2026-03-16 13:48:42 -07:00
Aleksandr Dobkin
29e35d77b1 Fix mesh transformation logic PrintObject::contour_z to handle off center cases 2026-03-16 00:56:52 -07:00
Aleksandr Dobkin
ba5b06196a Revert changes to 'ArcFitter' 2026-03-13 02:12:10 -07:00
Aleksandr Dobkin
9fae402d62 Fix scarf seams 2026-03-13 01:56:51 -07:00
Aleksandr Dobkin
59f6d75df7 Revert extraneous changes. 2026-03-11 17:20:12 -07:00
Aleksandr Dobkin
deb464854a Remove obsolete build and documentation files and clean up commented-out code 2026-03-11 02:47:32 -07:00
Aleksandr Dobkin
cf135c6843 Revert "fix: Exclude external spool from 16-material AMS limit"
This reverts commit 285d040e4a.
2026-03-11 02:36:12 -07:00
Aleksandr Dobkin
4c493dd0d3 Remove reference to nonplanar directory from .gitignore 2026-03-11 01:18:54 -07:00
Aleksandr Dobkin
b945c957d8 Merge branch 'main' into zaa 2026-03-11 01:04:44 -07:00
Aleksandr Dobkin
e8357f60d5 Fix ZAA test failure in test_extrusion_entity.cpp 2026-03-11 00:28:14 -07:00
Aleksandr Dobkin
52d33853cb Remove references to "/nonplanar" resource directory. 2026-03-11 00:12:21 -07:00
SoftFever
6a398a0347 Merge branch 'main' into feature/zaa-contouring 2026-02-10 22:34:27 +08:00
SoftFever
00eb461b1c Merge branch 'main' into feature/zaa-contouring 2026-02-10 13:53:52 +08:00
Matthias Nott
285d040e4a fix: Exclude external spool from 16-material AMS limit
External spools (virtual trays) are not AMS slots and should not count
toward the firmware's 16-material limit. Fixes blocking error when using
4 AMS units (16 slots) plus an external spool (17 total).

Fixes #12135
2026-02-09 23:09:25 +01:00
Matthias Nott
d5b4d266c7 fix: Eliminate redundant Z coordinates in ZAA gcode output
extrude_to_xyz() unconditionally emitted Z on every extrusion move
via emit_xyz(), even when Z hadn't changed. With ZAA enabled, this
produced ~987K redundant Z coordinates (98.2% of all Z emissions),
causing 10-20% file bloat.

Now compares quantized Z values before and after, and only emits Z
when it actually differs at export precision (0.001mm). Reduces
ZAA gcode Z emissions from 1,038,468 to 50,022 while preserving
all legitimate contouring Z changes.
2026-02-09 22:19:39 +01:00
Matthias Nott
90cf80a1f8 fix: Correct Polyline3::split_at point insertion order
The split point was being prepended (append_before) to p1 instead of
appended, causing it to be placed at the start of the segment rather
than the end. This resulted in rogue extrusion jumps (stringing)
across the model during ZAA sloped extrusions.

Also adds missing append/append_before calls in the exact-point
(index != -1) branch, which previously lost the split point entirely.
2026-02-09 22:19:31 +01:00
Matthias Nott
97a9c9fb68 docs: Simplify BUILD.md steps, remove redundant git install section 2026-02-09 21:18:48 +01:00
Matthias Nott
710c2a3854 docs: Add build script and step-by-step macOS build guide
- build.sh: Handles full lifecycle (deps, configure, incremental build)
  with auto-detection of architecture, CMake 4.x compat, and preflight checks
- BUILD.md: Beginner-friendly walkthrough from zero (no Xcode, no Homebrew,
  no git) to running OrcaSlicer.app
2026-02-09 21:16:27 +01:00
Matthias Nott
963f8d86b7 feat: Add Z Anti-Aliasing (ZAA) contouring support
Port Z Anti-Aliasing from BambuStudio-ZAA (https://github.com/adob/BambuStudio-ZAA)
to OrcaSlicer. ZAA eliminates stair-stepping on curved and sloped top surfaces
by raycasting each extrusion point against the original 3D mesh and micro-adjusting
Z height to follow the actual surface geometry.

Key changes:
- Add ContourZ.cpp raycasting algorithm (~330 lines)
- Extend geometry with 3D support (Point3, Line3, Polyline3, MultiPoint3)
- Template arc fitting for 2D/3D compatibility
- Change ExtrusionPath::polyline from Polyline to Polyline3
- Add 5 ZAA config options (zaa_enabled, zaa_min_z, etc.)
- Add posContouring pipeline step in PrintObject
- Update GCode writer for 3D coordinate output
- Add ZAA settings UI in Print Settings > Quality
- Add docs/ZAA.md with usage and implementation details

ZAA is opt-in and disabled by default. When disabled, the slicing pipeline
is unchanged.
2026-02-09 20:42:26 +01:00
127 changed files with 7606 additions and 1006 deletions

View File

@@ -34,6 +34,46 @@ jobs:
python3 ./scripts/orca_extra_profile_check.py 2>&1 | tee ${{ runner.temp }}/extra_json_check.log
exit ${PIPESTATUS[0]}
- name: Check profile indentation
id: indentation_check
continue-on-error: true
run: |
set +e
python3 - <<'PY' 2>&1 | tee ${{ runner.temp }}/indentation_check.log
import re
from pathlib import Path
import sys
profiles_root = Path("resources/profiles")
invalid_files = []
for file_path in sorted(profiles_root.rglob("*.json")):
try:
for line_number, line in enumerate(file_path.read_text(encoding="utf-8").splitlines(), start=1):
if not line.strip():
continue
leading_ws = re.match(r"^[ \t]*", line).group(0)
if " " in leading_ws:
invalid_files.append((file_path, line_number))
break
except Exception as exc:
print(f"[ERROR] Unable to read {file_path}: {exc}")
invalid_files.append((file_path, 0))
if invalid_files:
for path, line in invalid_files:
if line > 0:
print(f"[ERROR] Space indentation found in {path}:{line}")
else:
print(f"[ERROR] Could not validate indentation in {path}")
print("Use tab indentation in profile JSON files (1 tab per indentation level).")
print("Tip: run python3 ./scripts/orca_filament_lib.py --fix --force to normalize formatting.")
sys.exit(1)
print("All profile JSON files use tab-only indentation.")
PY
exit ${PIPESTATUS[0]}
# download
- name: Download
working-directory: ${{ github.workspace }}
@@ -62,7 +102,7 @@ jobs:
exit ${PIPESTATUS[0]}
- name: Prepare comment artifact
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
run: |
mkdir -p ${{ runner.temp }}/profile-check-results
@@ -79,6 +119,15 @@ jobs:
echo ""
fi
if [ "${{ steps.indentation_check.outcome }}" = "failure" ]; then
echo "### Indentation Check Failed"
echo ""
echo '```'
head -c 30000 ${{ runner.temp }}/indentation_check.log || echo "No output captured"
echo '```'
echo ""
fi
if [ "${{ steps.validate_system.outcome }}" = "failure" ]; then
echo "### System Profile Validation Failed"
echo ""
@@ -104,7 +153,7 @@ jobs:
echo "${{ github.event.pull_request.number }}" > ${{ runner.temp }}/profile-check-results/pr_number.txt
- name: Upload comment artifact
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
uses: actions/upload-artifact@v7
with:
name: profile-check-results
@@ -112,7 +161,7 @@ jobs:
retention-days: 1
- name: Fail if any check failed
if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.indentation_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
run: |
echo "One or more profile checks failed. See above for details."
exit 1

View File

@@ -785,8 +785,10 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
set(_arch "x64")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "X86")
set(_arch "x86")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
set(_arch "arm64")
else ()
message(FATAL_ERROR "Unable to detect architecture")
message(FATAL_ERROR "Unable to detect architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif ()
get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

6
deps/CMakeLists.txt vendored
View File

@@ -265,8 +265,12 @@ if (MSVC)
message(STATUS "\nDetected X86 compiler => building X86 deps bundle\n")
set(DEPS_ARCH "x86")
include("deps-windows.cmake")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
message(STATUS "\nDetected ARM64 compiler => building ARM64 deps bundle\n")
set(DEPS_ARCH "arm64")
include("deps-windows.cmake")
else ()
message(FATAL_ERROR "Unable to detect architecture")
message(FATAL_ERROR "Unable to detect architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif ()
elseif (APPLE)
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")

View File

@@ -36,8 +36,10 @@ if ("${DEPS_ARCH}" STREQUAL "x86")
set(DEP_PLATFORM "Win32")
elseif ("${DEPS_ARCH}" STREQUAL "x64")
set(DEP_PLATFORM "x64")
elseif ("${DEPS_ARCH}" STREQUAL "arm64")
set(DEP_PLATFORM "ARM64")
else ()
message(FATAL_ERROR "Unsupported OS architecture")
message(FATAL_ERROR "Unsupported OS architecture: ${DEPS_ARCH}")
endif ()
if (${DEP_DEBUG})
@@ -64,8 +66,11 @@ if ("${DEPS_ARCH}" STREQUAL "x86")
elseif ("${DEPS_ARCH}" STREQUAL "x64")
set(DEP_WXWIDGETS_TARGET "TARGET_CPU=X64")
set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib")
elseif ("${DEPS_ARCH}" STREQUAL "arm64")
set(DEP_WXWIDGETS_TARGET "TARGET_CPU=ARM64")
set(DEP_WXWIDGETS_LIBDIR "vc_arm64_lib")
else ()
message(FATAL_ERROR "Unsupported OS architecture")
message(FATAL_ERROR "Unsupported OS architecture: ${DEPS_ARCH}")
endif ()
find_package(Git REQUIRED)

View File

@@ -11072,7 +11072,7 @@ msgid "Gizmo assemble"
msgstr "Gizmo sestavit"
msgid "Gizmo brim ears"
msgstr "Gizmo přídavky okraje (uši)"
msgstr "Gizmo ouška lemu"
msgid "Zoom in"
msgstr "Přiblížit"
@@ -12583,13 +12583,13 @@ msgstr ""
"průtokovým poměrem filamentu a případně průtokovým poměrem objektu."
msgid "Set other flow ratios"
msgstr "Set other flow ratios"
msgstr "Nastavit další poměry průtoku"
msgid "Change flow ratios for other extrusion path types."
msgstr "Change flow ratios for other extrusion path types."
msgstr "Změnit poměry průtoku pro další typy extruzních drah."
msgid "First layer flow ratio"
msgstr "First layer flow ratio"
msgstr "Poměr průtoku první vrstvy"
msgid ""
"This factor affects the amount of material on the first layer for the "
@@ -12598,14 +12598,14 @@ msgid ""
"For the first layer, the actual flow ratio for each path role (does not "
"affect brims and skirts) will be multiplied by this value."
msgstr ""
"This factor affects the amount of material on the first layer for the "
"extrusion path roles listed in this section.\n"
"Tento faktor ovlivňuje množství materiálu na první vrstvě pro role extruzních "
"drah uvedené v této sekci.\n"
"\n"
"For the first layer, the actual flow ratio for each path role (does not "
"affect brims and skirts) will be multiplied by this value."
"Pro první vrstvu bude skutečný poměr průtoku pro každou roli dráhy (neovlivňuje "
"lem a sukni) vynásoben touto hodnotou."
msgid "Outer wall flow ratio"
msgstr "Outer wall flow ratio"
msgstr "Poměr průtoku vnější stěny"
msgid ""
"This factor affects the amount of material for outer walls.\n"
@@ -12613,13 +12613,13 @@ msgid ""
"The actual outer wall flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for outer walls.\n"
"Tento faktor ovlivňuje množství materiálu pro vnější stěny.\n"
"\n"
"The actual outer wall flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro vnější stěny se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Inner wall flow ratio"
msgstr "Inner wall flow ratio"
msgstr "Poměr průtoku vnitřní stěny"
msgid ""
"This factor affects the amount of material for inner walls.\n"
@@ -12627,13 +12627,13 @@ msgid ""
"The actual inner wall flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for inner walls.\n"
"Tento faktor ovlivňuje množství materiálu pro vnitřní stěny.\n"
"\n"
"The actual inner wall flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro vnitřní stěny se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Overhang flow ratio"
msgstr "Overhang flow ratio"
msgstr "Poměr průtoku převisů"
msgid ""
"This factor affects the amount of material for overhangs.\n"
@@ -12641,13 +12641,13 @@ msgid ""
"The actual overhang flow used is calculated by multiplying this value by the "
"filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for overhangs.\n"
"Tento faktor ovlivňuje množství materiálu pro převisy.\n"
"\n"
"The actual overhang flow used is calculated by multiplying this value by the "
"filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro převisy se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Sparse infill flow ratio"
msgstr "Sparse infill flow ratio"
msgstr "Poměr průtoku řídké výplně"
msgid ""
"This factor affects the amount of material for sparse infill.\n"
@@ -12655,13 +12655,13 @@ msgid ""
"The actual sparse infill flow used is calculated by multiplying this value "
"by the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for sparse infill.\n"
"Tento faktor ovlivňuje množství materiálu pro řídkou výplň.\n"
"\n"
"The actual sparse infill flow used is calculated by multiplying this value "
"by the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro řídkou výplň se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Internal solid infill flow ratio"
msgstr "Internal solid infill flow ratio"
msgstr "Poměr průtoku vnitřní plné výplně"
msgid ""
"This factor affects the amount of material for internal solid infill.\n"
@@ -12669,13 +12669,13 @@ msgid ""
"The actual internal solid infill flow used is calculated by multiplying this "
"value by the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for internal solid infill.\n"
"Tento faktor ovlivňuje množství materiálu pro vnitřní plnou výplň.\n"
"\n"
"The actual internal solid infill flow used is calculated by multiplying this "
"value by the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro vnitřní plnou výplň se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Gap fill flow ratio"
msgstr "Gap fill flow ratio"
msgstr "Poměr průtoku vyplnění mezer"
msgid ""
"This factor affects the amount of material for filling the gaps.\n"
@@ -12683,13 +12683,13 @@ msgid ""
"The actual gap filling flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for filling the gaps.\n"
"Tento faktor ovlivňuje množství materiálu pro vyplnění mezer.\n"
"\n"
"The actual gap filling flow used is calculated by multiplying this value by "
"the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro vyplnění mezer se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Support flow ratio"
msgstr "Support flow ratio"
msgstr "Poměr průtoku podpěr"
msgid ""
"This factor affects the amount of material for support.\n"
@@ -12697,13 +12697,13 @@ msgid ""
"The actual support flow used is calculated by multiplying this value by the "
"filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for support.\n"
"Tento faktor ovlivňuje množství materiálu pro podpěry.\n"
"\n"
"The actual support flow used is calculated by multiplying this value by the "
"filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro podpěry se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Support interface flow ratio"
msgstr "Support interface flow ratio"
msgstr "Poměr průtoku rozhraní podpěr"
msgid ""
"This factor affects the amount of material for the support interface.\n"
@@ -12711,10 +12711,10 @@ msgid ""
"The actual support interface flow used is calculated by multiplying this "
"value by the filament flow ratio, and if set, the object's flow ratio."
msgstr ""
"This factor affects the amount of material for the support interface.\n"
"Tento faktor ovlivňuje množství materiálu pro rozhraní podpěr.\n"
"\n"
"The actual support interface flow used is calculated by multiplying this "
"value by the filament flow ratio, and if set, the object's flow ratio."
"Skutečný průtok pro rozhraní podpěr se vypočítá vynásobením této hodnoty "
"poměrem průtoku filamentu a případně také poměrem průtoku objektu."
msgid "Precise wall"
msgstr "Přesná stěna"

View File

@@ -1,6 +1,6 @@
{
"name": "Creality",
"version": "02.03.02.70",
"version": "02.03.02.71",
"force_update": "0",
"description": "Creality configurations",
"machine_model_list": [

View File

@@ -5,6 +5,7 @@
"from": "system",
"setting_id": "GM001",
"instantiation": "true",
"printer_variant": "0.2",
"printer_settings_id": "Creality",
"printer_model": "Creality Ender-3 V3 KE",
"gcode_flavor": "klipper",

View File

@@ -5,6 +5,7 @@
"from": "system",
"setting_id": "GM001",
"instantiation": "true",
"printer_variant": "0.4",
"printer_settings_id": "Creality",
"printer_model": "Creality Ender-3 V3 KE",
"gcode_flavor": "klipper",

View File

@@ -5,6 +5,7 @@
"from": "system",
"setting_id": "GM001",
"instantiation": "true",
"printer_variant": "0.6",
"printer_settings_id": "Creality",
"printer_model": "Creality Ender-3 V3 KE",
"gcode_flavor": "klipper",

View File

@@ -5,6 +5,7 @@
"from": "system",
"setting_id": "GM001",
"instantiation": "true",
"printer_variant": "0.8",
"printer_settings_id": "Creality",
"printer_model": "Creality Ender-3 V3 KE",
"gcode_flavor": "klipper",

View File

@@ -1,6 +1,6 @@
{
"name": "Custom Printer",
"version": "02.03.02.60",
"version": "02.03.02.61",
"force_update": "0",
"description": "My configurations",
"machine_model_list": [

159
resources/profiles/LH.json Normal file
View File

@@ -0,0 +1,159 @@
{
"name": "LH",
"url": "https://github.com/lhndo/LH-Stinger",
"version": "01.00.00.00",
"force_update": "0",
"description": "LH 3D Printer Configuration",
"machine_model_list": [
{
"name": "LH Stinger",
"sub_path": "machine/LH Stinger.json"
},
{
"name": "LH Stinger MMU",
"sub_path": "machine/LH Stinger MMU.json"
}
],
"process_list": [
{
"name": "fdm_process_common",
"sub_path": "process/fdm_process_common.json"
},
{
"name": "fdm_process_lh_common",
"sub_path": "process/fdm_process_lh_common.json"
},
{
"name": "0.20mm Daily @LH Stinger",
"sub_path": "process/0.20mm Daily @LH Stinger.json"
},
{
"name": "0.25mm Vase Mode @LH Stinger",
"sub_path": "process/0.25mm Vase Mode @LH Stinger.json"
},
{
"name": "0.20mm TPU @LH Stinger",
"sub_path": "process/0.20mm TPU @LH Stinger.json"
},
{
"name": "0.20mm Strength @LH Stinger",
"sub_path": "process/0.20mm Strength @LH Stinger.json"
},
{
"name": "0.20mm Speed @LH Stinger",
"sub_path": "process/0.20mm Speed @LH Stinger.json"
},
{
"name": "0.20mm Solid @LH Stinger",
"sub_path": "process/0.20mm Solid @LH Stinger.json"
},
{
"name": "0.20mm Quiet @LH Stinger",
"sub_path": "process/0.20mm Quiet @LH Stinger.json"
},
{
"name": "0.20mm PETG @LH Stinger",
"sub_path": "process/0.20mm PETG @LH Stinger.json"
},
{
"name": "0.20mm MMU @LH Stinger",
"sub_path": "process/0.20mm MMU @LH Stinger.json"
},
{
"name": "0.10mm HueForge @LH Stinger",
"sub_path": "process/0.10mm HueForge @LH Stinger.json"
},
{
"name": "0.14mm Detail Strength @LH Stinger",
"sub_path": "process/0.14mm Detail Strength @LH Stinger.json"
},
{
"name": "0.14mm Detail @LH Stinger",
"sub_path": "process/0.14mm Detail @LH Stinger.json"
}
],
"filament_list": [
{
"name": "fdm_filament_common",
"sub_path": "filament/fdm_filament_common.json"
},
{
"name": "fdm_filament_abs",
"sub_path": "filament/fdm_filament_abs.json"
},
{
"name": "fdm_filament_asa",
"sub_path": "filament/fdm_filament_asa.json"
},
{
"name": "fdm_filament_pc",
"sub_path": "filament/fdm_filament_pc.json"
},
{
"name": "fdm_filament_pet",
"sub_path": "filament/fdm_filament_pet.json"
},
{
"name": "fdm_filament_pla",
"sub_path": "filament/fdm_filament_pla.json"
},
{
"name": "fdm_filament_tpu",
"sub_path": "filament/fdm_filament_tpu.json"
},
{
"name": "LHS ASA",
"sub_path": "filament/LHS ASA.json"
},
{
"name": "LHS ABS",
"sub_path": "filament/LHS ABS.json"
},
{
"name": "LHS TPU",
"sub_path": "filament/LHS TPU.json"
},
{
"name": "LHS PLA",
"sub_path": "filament/LHS PLA.json"
},
{
"name": "LHS TPU Foamy 78A",
"sub_path": "filament/LHS TPU Foamy 78A.json"
},
{
"name": "LHS PETG",
"sub_path": "filament/LHS PETG.json"
},
{
"name": "LHS PCTG",
"sub_path": "filament/LHS PCTG.json"
},
{
"name": "LHS PC CF",
"sub_path": "filament/LHS PC CF.json"
}
],
"machine_list": [
{
"name": "fdm_machine_common",
"sub_path": "machine/fdm_machine_common.json"
},
{
"name": "fdm_lh_common",
"sub_path": "machine/fdm_lh_common.json"
},
{
"name": "fdm_lh_mmu_common",
"sub_path": "machine/fdm_lh_mmu_common.json"
},
{
"name": "LH Stinger 0.4 nozzle",
"sub_path": "machine/LH Stinger 0.4 nozzle.json"
},
{
"name": "LH Stinger MMU 0.4 nozzle",
"sub_path": "machine/LH Stinger MMU 0.4 nozzle.json"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,355 @@
{
"name": "LHS ABS",
"type": "filament",
"filament_id": "LHF_abs",
"setting_id": "LHF_S_abs",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_asa",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"0"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"2"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"0"
],
"cool_plate_temp_initial_layer": [
"0"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"100"
],
"eng_plate_temp_initial_layer": [
"105"
],
"fan_cooling_layer_time": [
"25"
],
"fan_max_speed": [
"25"
],
"fan_min_speed": [
"25"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.04"
],
"filament_deretraction_speed": [
"nil"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.926"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"45"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"nil"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"nil"
],
"filament_settings_id": [
"LHS - ASA"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.07 FILAMENT_HEAT_CAPACITY=2.1\nMAX_FAN LINK_AUX=0"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"ASA"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"nil"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"4"
],
"hot_plate_temp": [
"105"
],
"hot_plate_temp_initial_layer": [
"105"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"-1"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"260"
],
"nozzle_temperature_initial_layer": [
"260"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"240"
],
"overhang_fan_speed": [
"50"
],
"overhang_fan_threshold": [
"50%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.019"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"15"
],
"slow_down_min_speed": [
"10"
],
"supertack_plate_temp": [
"0"
],
"supertack_plate_temp_initial_layer": [
"0"
],
"support_material_interface_fan_speed": [
"-1"
],
"temperature_vitrification": [
"110"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"100"
],
"textured_plate_temp_initial_layer": [
"105"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS ASA",
"filament_id": "LHF_asa",
"setting_id": "LHF_S_asa",
"type": "filament",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_asa",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"0"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"2"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"0"
],
"cool_plate_temp_initial_layer": [
"0"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"100"
],
"eng_plate_temp_initial_layer": [
"105"
],
"fan_cooling_layer_time": [
"25"
],
"fan_max_speed": [
"25"
],
"fan_min_speed": [
"25"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.04"
],
"filament_deretraction_speed": [
"nil"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.926"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"45"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"nil"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"nil"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.07 FILAMENT_HEAT_CAPACITY=2.1\nMAX_FAN LINK_AUX=0"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"ASA"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"nil"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"4"
],
"hot_plate_temp": [
"105"
],
"hot_plate_temp_initial_layer": [
"105"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"-1"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"260"
],
"nozzle_temperature_initial_layer": [
"260"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"240"
],
"overhang_fan_speed": [
"50"
],
"overhang_fan_threshold": [
"50%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.019"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"15"
],
"slow_down_min_speed": [
"10"
],
"supertack_plate_temp": [
"0"
],
"supertack_plate_temp_initial_layer": [
"0"
],
"support_material_interface_fan_speed": [
"-1"
],
"temperature_vitrification": [
"110"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"100"
],
"textured_plate_temp_initial_layer": [
"105"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,122 @@
{
"name": "LHS PC CF",
"type": "filament",
"filament_id": "LHF_pccf",
"setting_id": "LHF_S_pccf",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"additional_cooling_fan_speed": [
"0"
],
"close_fan_the_first_x_layers": [
"4"
],
"enable_pressure_advance": [
"1"
],
"fan_cooling_layer_time": [
"11"
],
"fan_max_speed": [
"5"
],
"fan_min_speed": [
"5"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_density": [
"1.18"
],
"filament_flow_ratio": [
"0.945"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_max_volumetric_speed": [
"35"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
"Extrusion Override set to a higher value\nAux disabled\nZ-Offset increased to 0.025 due to nozzle expansion at 300C"
],
"filament_retraction_length": [
"0.4"
],
"filament_shrink": [
"99.8%"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.36 FILAMENT_HEAT_CAPACITY=2.6\nMAX_FAN LINK_AUX=0"
],
"filament_type": [
"PC"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"hot_plate_temp": [
"105"
],
"hot_plate_temp_initial_layer": [
"105"
],
"is_custom_defined": "0",
"nozzle_temperature": [
"300"
],
"nozzle_temperature_initial_layer": [
"300"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"270"
],
"overhang_fan_speed": [
"35"
],
"pressure_advance": [
"0.025"
],
"slow_down_layer_time": [
"7"
],
"slow_down_min_speed": [
"12"
],
"filament_vendor": [
"LH Stinger"
],
"temperature_vitrification": [
"140"
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS PCTG",
"type": "filament",
"filament_id": "LHF_pctg",
"setting_id": "LHF_S_pctg",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"0"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"1"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"35"
],
"cool_plate_temp_initial_layer": [
"35"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"0"
],
"eng_plate_temp_initial_layer": [
"0"
],
"fan_cooling_layer_time": [
"13"
],
"fan_max_speed": [
"50"
],
"fan_min_speed": [
"20"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.24"
],
"filament_deretraction_speed": [
"25"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.953"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"25"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"10"
],
"filament_multitool_ramming_volume": [
"10"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"0.6"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"30"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.25 FILAMENT_HEAT_CAPACITY=5.5\nMAX_FAN LINK_AUX=0"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"PCTG"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"0"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"3"
],
"hot_plate_temp": [
"90"
],
"hot_plate_temp_initial_layer": [
"85"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"30"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"280"
],
"nozzle_temperature_initial_layer": [
"270"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"230"
],
"overhang_fan_speed": [
"50"
],
"overhang_fan_threshold": [
"50%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.038"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"12"
],
"slow_down_min_speed": [
"15"
],
"supertack_plate_temp": [
"45"
],
"supertack_plate_temp_initial_layer": [
"45"
],
"support_material_interface_fan_speed": [
"50"
],
"temperature_vitrification": [
"80"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"55"
],
"textured_plate_temp_initial_layer": [
"55"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS PETG",
"type": "filament",
"filament_id": "LHF_petg",
"setting_id": "LHF_S_petg",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"0"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"1"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"35"
],
"cool_plate_temp_initial_layer": [
"35"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"0"
],
"eng_plate_temp_initial_layer": [
"0"
],
"fan_cooling_layer_time": [
"15"
],
"fan_max_speed": [
"65"
],
"fan_min_speed": [
"35"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.24"
],
"filament_deretraction_speed": [
"nil"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.923"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"27"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"0.6"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"nil"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.27 FILAMENT_HEAT_CAPACITY=5.5\nMAX_FAN LINK_AUX=0"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"PETG"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"nil"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"3"
],
"hot_plate_temp": [
"80"
],
"hot_plate_temp_initial_layer": [
"80"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"50"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"260"
],
"nozzle_temperature_initial_layer": [
"260"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"230"
],
"overhang_fan_speed": [
"90"
],
"overhang_fan_threshold": [
"50%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.047"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"14"
],
"slow_down_min_speed": [
"15"
],
"supertack_plate_temp": [
"45"
],
"supertack_plate_temp_initial_layer": [
"45"
],
"support_material_interface_fan_speed": [
"80"
],
"temperature_vitrification": [
"80"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"55"
],
"textured_plate_temp_initial_layer": [
"55"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS PLA",
"type": "filament",
"filament_id": "LHF_pla",
"setting_id": "LHF_S_pla",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"70"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"1"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"35"
],
"cool_plate_temp_initial_layer": [
"35"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"0"
],
"eng_plate_temp_initial_layer": [
"0"
],
"fan_cooling_layer_time": [
"20"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"65"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.24"
],
"filament_deretraction_speed": [
"nil"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.95"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"45"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"nil"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"nil"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.24 FILAMENT_HEAT_CAPACITY=3.2\n; MAX_FAN LINK_AUX=0"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"PLA"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"nil"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"0"
],
"hot_plate_temp": [
"60"
],
"hot_plate_temp_initial_layer": [
"60"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"-1"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"235"
],
"nozzle_temperature_initial_layer": [
"230"
],
"nozzle_temperature_range_high": [
"280"
],
"nozzle_temperature_range_low": [
"190"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"25%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.02"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"8"
],
"slow_down_min_speed": [
"15"
],
"supertack_plate_temp": [
"45"
],
"supertack_plate_temp_initial_layer": [
"45"
],
"support_material_interface_fan_speed": [
"100"
],
"temperature_vitrification": [
"45"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"55"
],
"textured_plate_temp_initial_layer": [
"60"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS TPU Foamy 78A",
"type": "filament",
"filament_id": "LHF_ftpuf",
"setting_id": "LHF_S_ftpuf",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_tpu",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"55"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"1"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"30"
],
"cool_plate_temp_initial_layer": [
"30"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"30"
],
"eng_plate_temp_initial_layer": [
"30"
],
"fan_cooling_layer_time": [
"30"
],
"fan_max_speed": [
"60"
],
"fan_min_speed": [
"60"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.02"
],
"filament_deretraction_speed": [
"20"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.85"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"4"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"1.2"
],
"filament_retraction_minimum_travel": [
"1"
],
"filament_retraction_speed": [
"30"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.02 FILAMENT_HEAT_CAPACITY=2\n; MAX_FAN LINK_AUX=0 \nSET_PRESSURE_ADVANCE EXTRUDER=extruder SMOOTH_TIME=0.04"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"TPU"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"0"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"0"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"0"
],
"hot_plate_temp": [
"25"
],
"hot_plate_temp_initial_layer": [
"25"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"-1"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"265"
],
"nozzle_temperature_initial_layer": [
"260"
],
"nozzle_temperature_range_high": [
"280"
],
"nozzle_temperature_range_low": [
"240"
],
"overhang_fan_speed": [
"70"
],
"overhang_fan_threshold": [
"25%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.06"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"5"
],
"slow_down_min_speed": [
"20"
],
"supertack_plate_temp": [
"0"
],
"supertack_plate_temp_initial_layer": [
"0"
],
"support_material_interface_fan_speed": [
"100"
],
"temperature_vitrification": [
"30"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"35"
],
"textured_plate_temp_initial_layer": [
"35"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,352 @@
{
"name": "LHS TPU",
"type": "filament",
"filament_id": "LHF_ptpu_pl",
"setting_id": "LHF_S_ptpu_pl",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_tpu",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"activate_air_filtration": [
"0"
],
"activate_chamber_temp_control": [
"0"
],
"adaptive_pressure_advance": [
"0"
],
"adaptive_pressure_advance_bridges": [
"0"
],
"adaptive_pressure_advance_model": [
"0,0,0\n0,0,0"
],
"adaptive_pressure_advance_overhangs": [
"0"
],
"additional_cooling_fan_speed": [
"55"
],
"chamber_temperature": [
"0"
],
"close_fan_the_first_x_layers": [
"1"
],
"complete_print_exhaust_fan_speed": [
"70"
],
"cool_plate_temp": [
"30"
],
"cool_plate_temp_initial_layer": [
"30"
],
"default_filament_colour": [
""
],
"dont_slow_down_outer_wall": [
"0"
],
"during_print_exhaust_fan_speed": [
"70"
],
"enable_overhang_bridge_fan": [
"1"
],
"enable_pressure_advance": [
"1"
],
"eng_plate_temp": [
"30"
],
"eng_plate_temp_initial_layer": [
"30"
],
"fan_cooling_layer_time": [
"20"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"60"
],
"filament_adaptive_volumetric_speed": [
"0"
],
"filament_adhesiveness_category": [
"0"
],
"filament_change_length": [
"10"
],
"filament_cooling_final_speed": [
"0"
],
"filament_cooling_initial_speed": [
"0"
],
"filament_cooling_moves": [
"0"
],
"filament_cost": [
"20"
],
"filament_density": [
"1.22"
],
"filament_deretraction_speed": [
"20"
],
"filament_diameter": [
"1.75"
],
"filament_end_gcode": [
"; filament end gcode\n"
],
"filament_extruder_variant": [
"Direct Drive Standard"
],
"filament_flow_ratio": [
"0.965"
],
"filament_flush_temp": [
"0"
],
"filament_flush_volumetric_speed": [
"0"
],
"filament_ironing_flow": [
"nil"
],
"filament_ironing_inset": [
"nil"
],
"filament_ironing_spacing": [
"nil"
],
"filament_ironing_speed": [
"nil"
],
"filament_is_support": [
"0"
],
"filament_loading_speed": [
"0"
],
"filament_loading_speed_start": [
"0"
],
"filament_long_retractions_when_cut": [
"nil"
],
"filament_max_volumetric_speed": [
"20"
],
"filament_minimal_purge_on_wipe_tower": [
"0"
],
"filament_multitool_ramming": [
"0"
],
"filament_multitool_ramming_flow": [
"0"
],
"filament_multitool_ramming_volume": [
"0"
],
"filament_notes": [
""
],
"filament_printable": [
"3"
],
"filament_ramming_parameters": [
"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_lift_above": [
"nil"
],
"filament_retract_lift_below": [
"nil"
],
"filament_retract_lift_enforce": [
"Bottom Only"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_distances_when_cut": [
"nil"
],
"filament_retraction_length": [
"0.9"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retraction_speed": [
"35"
],
"filament_shrink": [
"100%"
],
"filament_shrinkage_compensation_z": [
"100%"
],
"filament_soluble": [
"0"
],
"filament_stamping_distance": [
"0"
],
"filament_stamping_loading_speed": [
"0"
],
"filament_start_gcode": [
"; filament start gcode\n; MPC_SET HEATER=extruder FILAMENT_DENSITY=1.22 FILAMENT_HEAT_CAPACITY=2\n; MAX_FAN LINK_AUX=0\nSET_PRESSURE_ADVANCE EXTRUDER=extruder SMOOTH_TIME=0.04"
],
"filament_toolchange_delay": [
"0"
],
"filament_tower_interface_pre_extrusion_dist": [
"10"
],
"filament_tower_interface_pre_extrusion_length": [
"0"
],
"filament_tower_interface_print_temp": [
"-1"
],
"filament_tower_interface_purge_volume": [
"20"
],
"filament_tower_ironing_area": [
"4"
],
"filament_type": [
"TPU"
],
"filament_unloading_speed": [
"0"
],
"filament_unloading_speed_start": [
"0"
],
"filament_wipe": [
"0"
],
"filament_wipe_distance": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_z_hop_types": [
"nil"
],
"full_fan_speed_layer": [
"0"
],
"hot_plate_temp": [
"30"
],
"hot_plate_temp_initial_layer": [
"30"
],
"idle_temperature": [
"0"
],
"internal_bridge_fan_speed": [
"-1"
],
"ironing_fan_speed": [
"-1"
],
"long_retractions_when_ec": [
"0"
],
"nozzle_temperature": [
"245"
],
"nozzle_temperature_initial_layer": [
"230"
],
"nozzle_temperature_range_high": [
"300"
],
"nozzle_temperature_range_low": [
"200"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"25%"
],
"pellet_flow_coefficient": [
"0.4157"
],
"pressure_advance": [
"0.08"
],
"reduce_fan_stop_start_freq": [
"1"
],
"required_nozzle_HRC": [
"3"
],
"retraction_distances_when_ec": [
"10"
],
"slow_down_for_layer_cooling": [
"1"
],
"slow_down_layer_time": [
"12"
],
"slow_down_min_speed": [
"12"
],
"supertack_plate_temp": [
"0"
],
"supertack_plate_temp_initial_layer": [
"0"
],
"support_material_interface_fan_speed": [
"100"
],
"temperature_vitrification": [
"30"
],
"textured_cool_plate_temp": [
"40"
],
"textured_cool_plate_temp_initial_layer": [
"40"
],
"textured_plate_temp": [
"35"
],
"textured_plate_temp_initial_layer": [
"35"
],
"filament_vendor": [
"LH Stinger"
],
"volumetric_speed_coefficients": [
""
]
}

View File

@@ -0,0 +1,88 @@
{
"type": "filament",
"name": "fdm_filament_abs",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"105"
],
"eng_plate_temp": [
"105"
],
"hot_plate_temp": [
"105"
],
"textured_plate_temp": [
"105"
],
"cool_plate_temp_initial_layer": [
"105"
],
"eng_plate_temp_initial_layer": [
"105"
],
"hot_plate_temp_initial_layer": [
"105"
],
"textured_plate_temp_initial_layer": [
"105"
],
"slow_down_for_layer_cooling": [
"1"
],
"close_fan_the_first_x_layers": [
"3"
],
"fan_cooling_layer_time": [
"30"
],
"filament_max_volumetric_speed": [
"28.6"
],
"filament_type": [
"ABS"
],
"filament_density": [
"1.04"
],
"filament_cost": [
"20"
],
"nozzle_temperature_initial_layer": [
"260"
],
"reduce_fan_stop_start_freq": [
"1"
],
"fan_max_speed": [
"80"
],
"fan_min_speed": [
"10"
],
"overhang_fan_threshold": [
"25%"
],
"overhang_fan_speed": [
"80"
],
"nozzle_temperature": [
"260"
],
"temperature_vitrification": [
"110"
],
"nozzle_temperature_range_low": [
"240"
],
"nozzle_temperature_range_high": [
"270"
],
"slow_down_min_speed": [
"10"
],
"slow_down_layer_time": [
"3"
]
}

View File

@@ -0,0 +1,88 @@
{
"type": "filament",
"name": "fdm_filament_asa",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"105"
],
"eng_plate_temp": [
"105"
],
"hot_plate_temp": [
"105"
],
"textured_plate_temp": [
"105"
],
"cool_plate_temp_initial_layer": [
"105"
],
"eng_plate_temp_initial_layer": [
"105"
],
"hot_plate_temp_initial_layer": [
"105"
],
"textured_plate_temp_initial_layer": [
"105"
],
"slow_down_for_layer_cooling": [
"1"
],
"close_fan_the_first_x_layers": [
"3"
],
"fan_cooling_layer_time": [
"35"
],
"filament_max_volumetric_speed": [
"28.6"
],
"filament_type": [
"ASA"
],
"filament_density": [
"1.04"
],
"filament_cost": [
"20"
],
"nozzle_temperature_initial_layer": [
"260"
],
"reduce_fan_stop_start_freq": [
"1"
],
"fan_max_speed": [
"80"
],
"fan_min_speed": [
"10"
],
"overhang_fan_threshold": [
"25%"
],
"overhang_fan_speed": [
"80"
],
"nozzle_temperature": [
"260"
],
"temperature_vitrification": [
"110"
],
"nozzle_temperature_range_low": [
"240"
],
"nozzle_temperature_range_high": [
"270"
],
"slow_down_min_speed": [
"10"
],
"slow_down_layer_time": [
"3"
]
}

View File

@@ -0,0 +1,141 @@
{
"type": "filament",
"name": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"hot_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"60"
],
"eng_plate_temp_initial_layer": [
"60"
],
"hot_plate_temp_initial_layer": [
"60"
],
"textured_plate_temp_initial_layer": [
"60"
],
"overhang_fan_threshold": [
"95%"
],
"overhang_fan_speed": [
"100"
],
"slow_down_for_layer_cooling": [
"1"
],
"close_fan_the_first_x_layers": [
"3"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_flow_ratio": [
"1"
],
"reduce_fan_stop_start_freq": [
"0"
],
"fan_cooling_layer_time": [
"60"
],
"filament_cost": [
"0"
],
"filament_density": [
"0"
],
"filament_deretraction_speed": [
"nil"
],
"filament_diameter": [
"1.75"
],
"filament_max_volumetric_speed": [
"0"
],
"filament_minimal_purge_on_wipe_tower": [
"15"
],
"filament_retraction_minimum_travel": [
"nil"
],
"filament_retract_before_wipe": [
"nil"
],
"filament_retract_when_changing_layer": [
"nil"
],
"filament_retraction_length": [
"nil"
],
"filament_z_hop": [
"nil"
],
"filament_retract_restart_extra": [
"nil"
],
"filament_retraction_speed": [
"nil"
],
"filament_settings_id": [
""
],
"filament_soluble": [
"0"
],
"filament_type": [
"PLA"
],
"filament_vendor": [
"Generic"
],
"filament_wipe": [
"nil"
],
"filament_wipe_distance": [
"nil"
],
"bed_type": [
"Cool Plate"
],
"nozzle_temperature_initial_layer": [
"200"
],
"full_fan_speed_layer": [
"0"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"35"
],
"slow_down_min_speed": [
"10"
],
"slow_down_layer_time": [
"8"
],
"filament_start_gcode": [
"; Filament gcode\n"
],
"nozzle_temperature": [
"200"
],
"temperature_vitrification": [
"100"
]
}

View File

@@ -0,0 +1,88 @@
{
"type": "filament",
"name": "fdm_filament_pc",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"0"
],
"eng_plate_temp": [
"110"
],
"hot_plate_temp": [
"110"
],
"textured_plate_temp": [
"110"
],
"cool_plate_temp_initial_layer": [
"0"
],
"eng_plate_temp_initial_layer": [
"110"
],
"hot_plate_temp_initial_layer": [
"110"
],
"textured_plate_temp_initial_layer": [
"110"
],
"slow_down_for_layer_cooling": [
"1"
],
"close_fan_the_first_x_layers": [
"3"
],
"fan_cooling_layer_time": [
"30"
],
"filament_max_volumetric_speed": [
"23.2"
],
"filament_type": [
"PC"
],
"filament_density": [
"1.04"
],
"filament_cost": [
"20"
],
"nozzle_temperature_initial_layer": [
"270"
],
"reduce_fan_stop_start_freq": [
"1"
],
"fan_max_speed": [
"60"
],
"fan_min_speed": [
"10"
],
"overhang_fan_threshold": [
"25%"
],
"overhang_fan_speed": [
"60"
],
"nozzle_temperature": [
"280"
],
"temperature_vitrification": [
"140"
],
"nozzle_temperature_range_low": [
"260"
],
"nozzle_temperature_range_high": [
"280"
],
"slow_down_min_speed": [
"10"
],
"slow_down_layer_time": [
"2"
]
}

View File

@@ -0,0 +1,82 @@
{
"type": "filament",
"name": "fdm_filament_pet",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"0"
],
"hot_plate_temp": [
"80"
],
"textured_plate_temp": [
"80"
],
"cool_plate_temp_initial_layer": [
"60"
],
"eng_plate_temp_initial_layer": [
"0"
],
"hot_plate_temp_initial_layer": [
"80"
],
"textured_plate_temp_initial_layer": [
"80"
],
"slow_down_for_layer_cooling": [
"1"
],
"close_fan_the_first_x_layers": [
"3"
],
"fan_cooling_layer_time": [
"20"
],
"filament_max_volumetric_speed": [
"25"
],
"filament_type": [
"PETG"
],
"filament_density": [
"1.27"
],
"filament_cost": [
"30"
],
"nozzle_temperature_initial_layer": [
"255"
],
"reduce_fan_stop_start_freq": [
"1"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"20"
],
"overhang_fan_speed": [
"100"
],
"nozzle_temperature": [
"255"
],
"temperature_vitrification": [
"80"
],
"nozzle_temperature_range_low": [
"220"
],
"nozzle_temperature_range_high": [
"260"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}

View File

@@ -0,0 +1,94 @@
{
"type": "filament",
"name": "fdm_filament_pla",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"fan_cooling_layer_time": [
"100"
],
"filament_max_volumetric_speed": [
"12"
],
"filament_type": [
"PLA"
],
"filament_density": [
"1.24"
],
"filament_cost": [
"20"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"hot_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"60"
],
"eng_plate_temp_initial_layer": [
"60"
],
"hot_plate_temp_initial_layer": [
"60"
],
"textured_plate_temp_initial_layer": [
"60"
],
"nozzle_temperature_initial_layer": [
"220"
],
"reduce_fan_stop_start_freq": [
"1"
],
"slow_down_for_layer_cooling": [
"1"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"100"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"close_fan_the_first_x_layers": [
"1"
],
"nozzle_temperature": [
"220"
],
"temperature_vitrification": [
"60"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"230"
],
"slow_down_min_speed": [
"10"
],
"slow_down_layer_time": [
"4"
],
"additional_cooling_fan_speed": [
"70"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}

View File

@@ -0,0 +1,88 @@
{
"type": "filament",
"name": "fdm_filament_tpu",
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"cool_plate_temp": [
"30"
],
"eng_plate_temp": [
"30"
],
"hot_plate_temp": [
"35"
],
"textured_plate_temp": [
"35"
],
"cool_plate_temp_initial_layer": [
"30"
],
"eng_plate_temp_initial_layer": [
"30"
],
"hot_plate_temp_initial_layer": [
"35"
],
"textured_plate_temp_initial_layer": [
"35"
],
"fan_cooling_layer_time": [
"100"
],
"filament_max_volumetric_speed": [
"15"
],
"filament_type": [
"TPU"
],
"filament_density": [
"1.24"
],
"filament_cost": [
"20"
],
"filament_retraction_length": [
"0.4"
],
"nozzle_temperature_initial_layer": [
"240"
],
"reduce_fan_stop_start_freq": [
"1"
],
"slow_down_for_layer_cooling": [
"1"
],
"fan_max_speed": [
"100"
],
"fan_min_speed": [
"100"
],
"overhang_fan_speed": [
"100"
],
"additional_cooling_fan_speed": [
"70"
],
"close_fan_the_first_x_layers": [
"1"
],
"nozzle_temperature": [
"240"
],
"temperature_vitrification": [
"60"
],
"nozzle_temperature_range_low": [
"200"
],
"nozzle_temperature_range_high": [
"250"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}

View File

@@ -0,0 +1,16 @@
{
"type": "machine",
"name": "LH Stinger 0.4 nozzle",
"inherits": "fdm_lh_common",
"from": "system",
"setting_id": "LHS_m01_04",
"instantiation": "true",
"printer_model": "LH Stinger",
"nozzle_diameter": [
"0.4"
],
"default_filament_profile": [
"LHS PLA"
],
"printer_variant": "0.4"
}

View File

@@ -0,0 +1,16 @@
{
"type": "machine",
"name": "LH Stinger MMU 0.4 nozzle",
"inherits": "fdm_lh_mmu_common",
"from": "system",
"setting_id": "LHS_m01_mmu_04",
"instantiation": "true",
"printer_model": "LH Stinger MMU",
"nozzle_diameter": [
"0.4"
],
"default_filament_profile": [
"LHS PLA"
],
"printer_variant": "0.4"
}

View File

@@ -0,0 +1,12 @@
{
"type": "machine_model",
"name": "LH Stinger MMU",
"model_id": "LHS_M_mmu",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "LH",
"bed_model": "LH_Stinger_buildplate_model.STL",
"bed_texture": "LH_Stinger_MMU_buildplate_texture.png",
"hotend_model": "",
"default_materials": "LHS PLA;LHS PETG;LHS PCTG;LHS ASA;LHS ABS;LHS PC CF;LHS TPU Foamy 78A;LHS TPU;"
}

View File

@@ -0,0 +1,12 @@
{
"type": "machine_model",
"name": "LH Stinger",
"model_id": "LHS_M_base",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "LH",
"bed_model": "LH_Stinger_buildplate_model.STL",
"bed_texture": "LH_Stinger_buildplate_texture.png",
"hotend_model": "",
"default_materials": "LHS PLA;LHS PETG;LHS PCTG;LHS ASA;LHS ABS;LHS PC CF;LHS TPU Foamy 78A;LHS TPU;"
}

View File

@@ -0,0 +1,157 @@
{
"type": "machine",
"name": "fdm_lh_common",
"inherits": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "klipper",
"machine_max_acceleration_e": [
"5000",
"5000"
],
"machine_max_acceleration_extruding": [
"200000",
"20000"
],
"machine_max_acceleration_retracting": [
"200000",
"5000"
],
"machine_max_acceleration_travel": [
"20000",
"20000"
],
"machine_max_acceleration_x": [
"200000",
"20000"
],
"machine_max_acceleration_y": [
"200000",
"20000"
],
"machine_max_acceleration_z": [
"2000",
"200"
],
"machine_max_speed_e": [
"200",
"25"
],
"machine_max_speed_x": [
"1000",
"200"
],
"machine_max_speed_y": [
"1000",
"200"
],
"machine_max_speed_z": [
"100",
"12"
],
"machine_max_jerk_e": [
"15",
"2.5"
],
"machine_max_jerk_x": [
"15",
"9"
],
"machine_max_jerk_y": [
"15",
"9"
],
"machine_max_jerk_z": [
"15",
"0.4"
],
"machine_min_extruding_rate": [
"0",
"0"
],
"machine_min_travel_rate": [
"0",
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_area": [
"18x38",
"218x38",
"218x238",
"18x238"
],
"printable_height": "180",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"printer_settings_id": "",
"printer_technology": "FFF",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"1"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"0.3"
],
"retract_length_toolchange": [
"0"
],
"z_hop": [
"0.2"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"40"
],
"deretraction_speed": [
"30"
],
"retract_lift_enforce": [
"Top and Bottom"
],
"z_hop_types": [
"Auto Lift"
],
"silent_mode": "0",
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"manual_filament_change": "1",
"wipe": [
"1"
],
"default_filament_profile": [
"LH Generic PLA"
],
"enable_filament_ramming": "0",
"default_print_profile": "0.20mm Daily @LH Stinger",
"bed_exclude_area": [
"0x0"
],
"machine_start_gcode": "PRINT_START_LHS BED=[bed_temperature_initial_layer_single] HOTEND=[nozzle_temperature_initial_layer] AUTOMESH=1 AUTOPURGE=1 QUIETMODE={if print_preset =~ /.*Quiet.*/ }1{else}0{endif}\n",
"machine_end_gcode": "PRINT_END",
"layer_change_gcode": ";AFTER_LAYER_CHANGES\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "PAUSE",
"scan_first_layer": "0",
"nozzle_type": [
"brass"
],
"bed_temperature_formula": "by_first_filament",
"auxiliary_fan": "1"
}

View File

@@ -0,0 +1,21 @@
{
"type": "machine",
"name": "fdm_lh_mmu_common",
"inherits": "fdm_lh_common",
"from": "system",
"instantiation": "false",
"cooling_tube_length": "0",
"cooling_tube_retraction": "0",
"enable_filament_ramming": "0",
"extra_loading_move": "0",
"machine_start_gcode": " _SP_PRINT_START LANE=[initial_tool] TEMP=[nozzle_temperature_initial_layer]\n\nPRINT_START_LHS BED=[bed_temperature_initial_layer_single] HOTEND=[nozzle_temperature_initial_layer] AUTOMESH=1 AUTOPURGE=1 QUIETMODE={if print_preset =~ /.*Quiet.*/ }1{else}0{endif}\n\n",
"change_filament_gcode": " _SP_SET_PURGE PURGE=[first_flush_volume] ",
"layer_change_gcode": ";AFTER_LAYER_CHANGES\n;[layer_z]",
"machine_end_gcode": "PRINT_END\n\n_SP_PRINT_END",
"machine_tool_change_time": "20",
"parking_pos_retraction": "0",
"manual_filament_change": "0",
"retract_length_toolchange": [
"0"
]
}

View File

@@ -0,0 +1,119 @@
{
"type": "machine",
"name": "fdm_machine_common",
"from": "system",
"instantiation": "false",
"printer_technology": "FFF",
"deretraction_speed": [
"40"
],
"extruder_colour": [
"#FCE94F"
],
"extruder_offset": [
"0x0"
],
"gcode_flavor": "marlin",
"silent_mode": "0",
"machine_max_acceleration_e": [
"5000"
],
"machine_max_acceleration_extruding": [
"10000"
],
"machine_max_acceleration_retracting": [
"1000"
],
"machine_max_acceleration_x": [
"10000"
],
"machine_max_acceleration_y": [
"10000"
],
"machine_max_acceleration_z": [
"500"
],
"machine_max_speed_e": [
"60"
],
"machine_max_speed_x": [
"500"
],
"machine_max_speed_y": [
"500"
],
"machine_max_speed_z": [
"10"
],
"machine_max_jerk_e": [
"5"
],
"machine_max_jerk_x": [
"8"
],
"machine_max_jerk_y": [
"8"
],
"machine_max_jerk_z": [
"0.4"
],
"machine_min_extruding_rate": [
"0"
],
"machine_min_travel_rate": [
"0"
],
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"printable_height": "250",
"extruder_clearance_radius": "65",
"extruder_clearance_height_to_rod": "36",
"extruder_clearance_height_to_lid": "140",
"nozzle_diameter": [
"0.4"
],
"printer_settings_id": "",
"printer_variant": "0.4",
"retraction_minimum_travel": [
"2"
],
"retract_before_wipe": [
"70%"
],
"retract_when_changing_layer": [
"1"
],
"retraction_length": [
"1"
],
"retract_length_toolchange": [
"1"
],
"z_hop": [
"0"
],
"retract_restart_extra": [
"0"
],
"retract_restart_extra_toolchange": [
"0"
],
"retraction_speed": [
"60"
],
"single_extruder_multi_material": "1",
"change_filament_gcode": "",
"wipe": [
"1"
],
"default_print_profile": "",
"machine_start_gcode": "G0 Z20 F9000\nG92 E0; G1 E-10 F1200\nG28\nM970 Q1 A10 B10 C130 K0\nM970 Q1 A10 B131 C250 K1\nM974 Q1 S1 P0\nM970 Q0 A10 B10 C130 H20 K0\nM970 Q0 A10 B131 C250 K1\nM974 Q0 S1 P0\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nG29 ;Home\nG90;\nG92 E0 ;Reset Extruder \nG1 Z2.0 F3000 ;Move Z Axis up \nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nM109 S205;\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder \nG1 X110 Y110 Z2.0 F3000 ;Move Z Axis up",
"machine_end_gcode": "M400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-4.0 F3600; retract \nG91\nG1 Z3;\nM104 S0 ; turn off hotend\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nG90 \nG0 X110 Y200 F3600 \nprint_end",
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n",
"machine_pause_gcode": "M601"
}

View File

@@ -0,0 +1,42 @@
{
"type": "process",
"name": "0.10mm HueForge @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_hueforge",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"bottom_shell_layers": "999",
"bottom_solid_infill_flow_ratio": "0.98",
"detect_narrow_internal_solid_infill": "0",
"ensure_vertical_shell_thickness": "none",
"initial_layer_acceleration": "1000",
"initial_layer_infill_speed": "150",
"initial_layer_print_height": "0.16",
"initial_layer_speed": "80",
"layer_height": "0.1",
"max_travel_detour_distance": "60",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"reduce_crossing_wall": "1",
"skirt_loops": "1",
"slice_closing_radius": "0.042",
"sparse_infill_density": "0%",
"top_bottom_infill_wall_overlap": "15%",
"top_shell_layers": "0",
"top_solid_infill_flow_ratio": "0.98",
"brim_type": "no_brim",
"wall_generator": "arachne",
"wall_sequence": "inner wall/outer wall",
"reduce_infill_retraction": "1",
"gap_fill_target": "nowhere",
"filter_out_gap_fill": "0.5",
"wall_loops": "1"
}

View File

@@ -0,0 +1,54 @@
{
"type": "process",
"name": "0.14mm Detail @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_detail",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"bottom_shell_layers": "5",
"bridge_flow": "1.2",
"default_jerk": "10",
"enable_support": "1",
"ensure_vertical_shell_thickness": "ensure_moderate",
"filter_out_gap_fill": "10",
"infill_jerk": "10",
"infill_wall_overlap": "10%",
"initial_layer_infill_speed": "90",
"initial_layer_jerk": "10",
"initial_layer_travel_speed": "250",
"inner_wall_jerk": "10",
"internal_bridge_flow": "1.2",
"layer_height": "0.14",
"max_travel_detour_distance": "50",
"outer_wall_jerk": "10",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"reduce_crossing_wall": "1",
"skirt_loops": "2",
"slow_down_layers": "2",
"small_perimeter_speed": "75%",
"small_perimeter_threshold": "3",
"sparse_infill_pattern": "rectilinear",
"sparse_infill_density": "15%",
"support_angle": "45",
"support_base_pattern": "rectilinear",
"support_base_pattern_spacing": "1.5",
"support_bottom_z_distance": "0.15",
"support_style": "organic",
"support_type": "tree(auto)",
"top_shell_layers": "6",
"top_surface_jerk": "10",
"wall_generator": "arachne",
"min_length_factor": "0.5",
"gap_fill_target": "nowhere",
"wall_loops": "3",
"travel_jerk": "10"
}

View File

@@ -0,0 +1,67 @@
{
"type": "process",
"name": "0.14mm Detail Strength @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_detail_strength",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"bottom_shell_layers": "6",
"bottom_shell_thickness": "0.8",
"bridge_acceleration": "7500",
"bridge_flow": "1.2",
"brim_width": "3",
"default_acceleration": "15000",
"default_jerk": "10",
"gap_infill_speed": "200",
"infill_anchor": "1000",
"infill_anchor_max": "1000",
"infill_jerk": "10",
"initial_layer_infill_speed": "90",
"initial_layer_jerk": "10",
"initial_layer_travel_speed": "250",
"inner_wall_acceleration": "10000",
"inner_wall_speed": "200",
"inner_wall_jerk": "10",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_speed": "200",
"layer_height": "0.14",
"max_travel_detour_distance": "50",
"outer_wall_acceleration": "7500",
"outer_wall_jerk": "10",
"outer_wall_speed": "200",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"reduce_crossing_wall": "1",
"skirt_loops": "2",
"slow_down_layers": "2",
"small_perimeter_speed": "75%",
"small_perimeter_threshold": "3",
"sparse_infill_acceleration": "15000",
"sparse_infill_speed": "200",
"sparse_infill_density": "40%",
"sparse_infill_pattern": "gyroid",
"support_base_pattern_spacing": "1.5",
"support_bottom_interface_spacing": "0.3",
"support_bottom_z_distance": "0.15",
"support_interface_speed": "300",
"support_speed": "200",
"support_type": "normal(manual)",
"top_shell_layers": "7",
"top_shell_thickness": "1",
"top_surface_acceleration": "7500",
"top_surface_jerk": "10",
"top_surface_speed": "200",
"travel_jerk": "10",
"wall_generator": "arachne",
"wall_sequence": "inner wall/outer wall",
"top_bottom_infill_wall_overlap": "25%",
"wall_loops": "4"
}

View File

@@ -0,0 +1,12 @@
{
"type": "process",
"name": "0.20mm Daily @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_daily",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
]
}

View File

@@ -0,0 +1,48 @@
{
"type": "process",
"name": "0.20mm MMU @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_mmu",
"instantiation": "true",
"compatible_printers": [
"LH Stinger MMU 0.4 nozzle"
],
"bottom_surface_pattern": "monotonicline",
"bridge_acceleration": "7000",
"default_jerk": "10",
"detect_narrow_internal_solid_infill": "0",
"filter_out_gap_fill": "1",
"gap_infill_speed": "220",
"infill_jerk": "10",
"infill_wall_overlap": "8%",
"initial_layer_infill_speed": "120",
"initial_layer_jerk": "10",
"initial_layer_line_width": "0.4",
"inner_wall_acceleration": "15000",
"inner_wall_jerk": "10",
"inner_wall_speed": "220",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_speed": "220",
"only_one_wall_first_layer": "1",
"outer_wall_jerk": "10",
"outer_wall_speed": "220",
"prime_tower_width": "80",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "50%",
"small_perimeter_threshold": "2",
"sparse_infill_acceleration": "15000",
"sparse_infill_pattern": "rectilinear",
"sparse_infill_speed": "220",
"top_bottom_infill_wall_overlap": "8%",
"top_surface_jerk": "10",
"top_surface_speed": "150",
"wall_generator": "arachne",
"sparse_infill_density": "15%",
"travel_jerk": "10"
}

View File

@@ -0,0 +1,74 @@
{
"type": "process",
"name": "0.20mm PETG @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_petg",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "90%",
"bottom_shell_layers": "5",
"bridge_acceleration": "3000",
"bridge_density": "95%",
"bridge_flow": "1.1",
"bridge_speed": "30",
"brim_ears_max_angle": "180",
"brim_object_gap": "0.04",
"default_acceleration": "15000",
"default_jerk": "10",
"filter_out_gap_fill": "1",
"gap_infill_speed": "200",
"infill_jerk": "10",
"infill_wall_overlap": "10%",
"initial_layer_infill_speed": "100",
"initial_layer_jerk": "10",
"initial_layer_print_height": "0.25",
"initial_layer_travel_speed": "250",
"inner_wall_acceleration": "15000",
"inner_wall_speed": "200",
"inner_wall_jerk": "10",
"inner_wall_line_width": "0.44",
"internal_bridge_speed": "50",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_speed": "200",
"internal_solid_infill_line_width": "0.44",
"line_width": "0.44",
"max_travel_detour_distance": "50",
"outer_wall_jerk": "10",
"outer_wall_line_width": "0.44",
"outer_wall_speed": "200",
"overhang_1_4_speed": "60%",
"overhang_2_4_speed": "40",
"overhang_3_4_speed": "20",
"overhang_reverse_internal_only": "1",
"overhang_reverse_threshold": "0%",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "60%",
"reduce_crossing_wall": "1",
"skirt_loops": "2",
"slow_down_layers": "2",
"small_perimeter_threshold": "10",
"sparse_infill_acceleration": "15000",
"sparse_infill_speed": "200",
"sparse_infill_line_width": "0.44",
"support_interface_speed": "200",
"support_line_width": "0.42",
"support_speed": "200",
"top_bottom_infill_wall_overlap": "18%",
"top_shell_layers": "6",
"top_surface_acceleration": "5000",
"top_surface_jerk": "10",
"top_surface_speed": "130",
"travel_jerk": "10",
"wall_loops": "3",
"gap_fill_target": "nowhere",
"wipe_tower_max_purge_speed": "150"
}

View File

@@ -0,0 +1,53 @@
{
"type": "process",
"name": "0.20mm Quiet @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_quiet",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "75%",
"bridge_acceleration": "5000",
"bridge_speed": "40",
"default_acceleration": "10000",
"default_jerk": "5",
"filter_out_gap_fill": "10",
"gap_infill_speed": "200",
"infill_jerk": "5",
"infill_wall_overlap": "10%",
"initial_layer_infill_speed": "100",
"initial_layer_jerk": "5",
"initial_layer_travel_speed": "180",
"inner_wall_acceleration": "10000",
"inner_wall_jerk": "5",
"internal_bridge_speed": "60",
"internal_solid_infill_acceleration": "10000",
"outer_wall_acceleration": "5000",
"outer_wall_jerk": "5",
"outer_wall_speed": "200",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "60%",
"sparse_infill_acceleration": "10000",
"sparse_infill_pattern": "rectilinear",
"support_interface_speed": "170",
"support_speed": "170",
"top_surface_jerk": "5",
"top_surface_speed": "200",
"inner_wall_speed": "200",
"sparse_infill_speed": "200",
"internal_solid_infill_speed": "200",
"travel_acceleration": "10000",
"travel_jerk": "5",
"sparse_infill_density": "15%",
"accel_to_decel_enable": "1",
"gap_fill_target": "nowhere",
"travel_speed": "200"
}

View File

@@ -0,0 +1,64 @@
{
"type": "process",
"name": "0.20mm Solid @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_solid",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "90%",
"bottom_shell_layers": "2",
"bridge_acceleration": "5000",
"bridge_density": "97%",
"brim_object_gap": "0.04",
"default_acceleration": "15000",
"default_jerk": "10",
"detect_narrow_internal_solid_infill": "0",
"enable_support": "1",
"ensure_vertical_shell_thickness": "none",
"filter_out_gap_fill": "2",
"gap_infill_speed": "200",
"infill_jerk": "10",
"infill_wall_overlap": "18%",
"initial_layer_jerk": "10",
"initial_layer_line_width": "0.45",
"initial_layer_print_height": "0.25",
"inner_wall_acceleration": "15000",
"inner_wall_jerk": "10",
"internal_solid_infill_acceleration": "15000",
"outer_wall_jerk": "10",
"outer_wall_speed": "200",
"overhang_1_4_speed": "60%",
"overhang_2_4_speed": "40",
"overhang_3_4_speed": "20",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "60%",
"small_perimeter_threshold": "7",
"sparse_infill_acceleration": "15000",
"sparse_infill_density": "98%",
"sparse_infill_pattern": "rectilinear",
"support_interface_speed": "200",
"support_speed": "200",
"top_shell_layers": "2",
"top_shell_thickness": "0.6",
"top_solid_infill_flow_ratio": "0.96",
"top_surface_acceleration": "5000",
"top_surface_jerk": "10",
"top_surface_speed": "150",
"inner_wall_speed": "200",
"sparse_infill_speed": "200",
"internal_solid_infill_speed": "200",
"internal_bridge_density": "95%",
"internal_bridge_speed": "150",
"gap_fill_target": "nowhere",
"wall_loops": "3",
"travel_jerk": "10"
}

View File

@@ -0,0 +1,43 @@
{
"type": "process",
"name": "0.20mm Speed @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_speed",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"bridge_acceleration": "15000",
"default_acceleration": "30000",
"filter_out_gap_fill": "10",
"infill_wall_overlap": "10%",
"initial_layer_speed": "90",
"inner_wall_acceleration": "30000",
"inner_wall_speed": "600",
"internal_solid_infill_acceleration": "30000",
"internal_solid_infill_speed": "600",
"outer_wall_acceleration": "15000",
"outer_wall_speed": "600",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "80%",
"sparse_infill_acceleration": "30000",
"sparse_infill_pattern": "rectilinear",
"sparse_infill_speed": "600",
"support_bottom_z_distance": "0.15",
"support_expansion": "2",
"support_interface_top_layers": "3",
"support_object_xy_distance": "0.25",
"top_surface_acceleration": "15000",
"top_surface_speed": "300",
"travel_acceleration": "30000",
"sparse_infill_density": "15%",
"gap_fill_target": "nowhere",
"travel_speed": "600"
}

View File

@@ -0,0 +1,66 @@
{
"type": "process",
"name": "0.20mm Strength @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_strength",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "90%",
"bottom_shell_layers": "5",
"bridge_acceleration": "5000",
"bridge_flow": "1.4",
"brim_object_gap": "0.04",
"default_acceleration": "15000",
"default_jerk": "10",
"filter_out_gap_fill": "1",
"gap_infill_speed": "200",
"infill_anchor": "1000",
"infill_anchor_max": "1000",
"infill_jerk": "10",
"initial_layer_infill_speed": "120",
"initial_layer_jerk": "10",
"initial_layer_speed": "90",
"initial_layer_travel_speed": "250",
"inner_wall_acceleration": "15000",
"inner_wall_jerk": "10",
"inner_wall_line_width": "0.46",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_line_width": "0.46",
"line_width": "0.46",
"outer_wall_jerk": "10",
"outer_wall_line_width": "0.46",
"outer_wall_speed": "200",
"overhang_1_4_speed": "60%",
"overhang_2_4_speed": "40",
"overhang_3_4_speed": "20",
"precise_outer_wall": "0",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"sparse_infill_acceleration": "15000",
"sparse_infill_density": "40%",
"sparse_infill_line_width": "0.46",
"sparse_infill_pattern": "gyroid",
"support_bottom_z_distance": "0.15",
"support_interface_speed": "200",
"support_line_width": "0.42",
"support_speed": "200",
"top_shell_layers": "6",
"top_shell_thickness": "1",
"top_surface_acceleration": "5000",
"top_surface_jerk": "10",
"top_surface_speed": "200",
"inner_wall_speed": "200",
"sparse_infill_speed": "200",
"internal_solid_infill_speed": "200",
"travel_jerk": "10",
"wall_sequence": "inner wall/outer wall",
"wall_loops": "4"
}

View File

@@ -0,0 +1,82 @@
{
"type": "process",
"name": "0.20mm TPU @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_tpu",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "90%",
"bridge_acceleration": "5000",
"bridge_density": "95%",
"bridge_flow": "1.4",
"bridge_speed": "40",
"brim_ears_max_angle": "180",
"brim_object_gap": "0.02",
"default_acceleration": "15000",
"default_jerk": "5",
"elefant_foot_compensation": "0.15",
"filter_out_gap_fill": "40",
"gap_infill_speed": "200",
"infill_jerk": "5",
"initial_layer_infill_speed": "70",
"initial_layer_jerk": "5",
"initial_layer_print_height": "0.25",
"initial_layer_speed": "40",
"initial_layer_travel_speed": "200",
"inner_wall_acceleration": "15000",
"inner_wall_jerk": "5",
"inner_wall_line_width": "0.46",
"internal_bridge_flow": "1.2",
"internal_bridge_speed": "50",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_line_width": "0.46",
"internal_solid_infill_speed": "180",
"line_width": "0.46",
"max_travel_detour_distance": "50",
"outer_wall_jerk": "5",
"outer_wall_line_width": "0.46",
"outer_wall_speed": "150",
"overhang_1_4_speed": "60%",
"overhang_2_4_speed": "40",
"overhang_3_4_speed": "20",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"raft_first_layer_density": "80%",
"reduce_crossing_wall": "1",
"skirt_loops": "2",
"slow_down_layers": "2",
"small_perimeter_speed": "60%",
"small_perimeter_threshold": "10",
"sparse_infill_acceleration": "15000",
"sparse_infill_line_width": "0.46",
"sparse_infill_speed": "150",
"sparse_infill_density": "15%",
"staggered_inner_seams": "1",
"support_expansion": "2",
"support_interface_speed": "200",
"support_line_width": "0.42",
"support_speed": "200",
"top_bottom_infill_wall_overlap": "18%",
"top_surface_acceleration": "5000",
"top_surface_jerk": "5",
"top_surface_line_width": "0.42",
"top_surface_speed": "150",
"travel_jerk": "10",
"wipe_speed": "80",
"inner_wall_speed": "200",
"ensure_vertical_shell_thickness": "ensure_moderate",
"wall_sequence": "inner wall/outer wall",
"wall_loops": "3",
"gap_fill_target": "nowhere",
"reduce_infill_retraction": "1",
"infill_wall_overlap": "22%",
"wipe_tower_max_purge_speed": "80"
}

View File

@@ -0,0 +1,70 @@
{
"type": "process",
"name": "0.25mm Vase Mode @LH Stinger",
"inherits": "fdm_process_lh_common",
"from": "system",
"setting_id": "LHS_P_vase_mode",
"instantiation": "true",
"compatible_printers": [
"LH Stinger 0.4 nozzle",
"LH Stinger MMU 0.4 nozzle"
],
"accel_to_decel_factor": "90%",
"bottom_shell_layers": "5",
"bridge_acceleration": "5000",
"bridge_flow": "1.4",
"brim_object_gap": "0.04",
"default_acceleration": "15000",
"default_jerk": "10",
"filter_out_gap_fill": "1",
"gap_infill_speed": "200",
"infill_jerk": "10",
"infill_wall_overlap": "10%",
"initial_layer_jerk": "10",
"initial_layer_line_width": "0.65",
"initial_layer_print_height": "0.25",
"initial_layer_speed": "80",
"initial_layer_travel_speed": "250",
"inner_wall_acceleration": "15000",
"inner_wall_jerk": "10",
"inner_wall_line_width": "0.46",
"internal_solid_infill_acceleration": "15000",
"internal_solid_infill_line_width": "0.46",
"layer_height": "0.25",
"line_width": "0.46",
"notes": "Decrease your Filament - Minimum layer time to ~2 seconds and set your fan speeds to be constant",
"outer_wall_jerk": "10",
"outer_wall_line_width": "0.65",
"outer_wall_speed": "200",
"overhang_1_4_speed": "60%",
"overhang_2_4_speed": "40",
"overhang_3_4_speed": "20",
"print_extruder_id": [
"1"
],
"print_extruder_variant": [
"Direct Drive Standard"
],
"sparse_infill_acceleration": "15000",
"sparse_infill_density": "0%",
"sparse_infill_line_width": "0.46",
"sparse_infill_pattern": "3dhoneycomb",
"spiral_mode": "1",
"spiral_mode_smooth": "1",
"support_interface_speed": "200",
"support_line_width": "0.42",
"support_speed": "200",
"top_bottom_infill_wall_overlap": "10%",
"top_shell_layers": "0",
"top_shell_thickness": "1",
"top_surface_acceleration": "5000",
"top_surface_jerk": "10",
"top_surface_speed": "200",
"inner_wall_speed": "200",
"sparse_infill_speed": "200",
"internal_solid_infill_speed": "200",
"wall_sequence": "inner wall/outer wall",
"travel_jerk": "10",
"skirt_loops": "1",
"wall_loops": "1"
}

View File

@@ -0,0 +1,108 @@
{
"type": "process",
"name": "fdm_process_common",
"from": "system",
"instantiation": "false",
"adaptive_layer_height": "0",
"reduce_crossing_wall": "0",
"max_travel_detour_distance": "0",
"bottom_surface_pattern": "monotonic",
"bottom_shell_thickness": "0",
"bridge_speed": "50",
"brim_width": "5",
"brim_object_gap": "0.1",
"compatible_printers": [],
"compatible_printers_condition": "",
"print_sequence": "by layer",
"default_acceleration": "1000",
"initial_layer_acceleration": "500",
"top_surface_acceleration": "1000",
"travel_acceleration": "1000",
"inner_wall_acceleration": "1000",
"outer_wall_acceleration": "700",
"bridge_no_support": "0",
"draft_shield": "disabled",
"elefant_foot_compensation": "0",
"enable_arc_fitting": "0",
"wall_infill_order": "inner wall/outer wall/infill",
"infill_direction": "45",
"sparse_infill_density": "15%",
"sparse_infill_pattern": "crosshatch",
"initial_layer_print_height": "0.2",
"infill_combination": "0",
"infill_wall_overlap": "25%",
"interface_shells": "0",
"ironing_flow": "10%",
"ironing_spacing": "0.15",
"ironing_speed": "30",
"ironing_type": "no ironing",
"reduce_infill_retraction": "1",
"filename_format": "{input_filename_base}_{layer_height}mm_{filament_type[initial_tool]}_{printer_model}_{print_time}.gcode",
"detect_overhang_wall": "1",
"slowdown_for_curled_perimeters": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "10",
"line_width": "110%",
"inner_wall_line_width": "110%",
"outer_wall_line_width": "100%",
"top_surface_line_width": "93.75%",
"sparse_infill_line_width": "110%",
"initial_layer_line_width": "120%",
"internal_solid_infill_line_width": "120%",
"support_line_width": "96%",
"wall_loops": "3",
"print_settings_id": "",
"raft_layers": "0",
"seam_position": "aligned",
"skirt_distance": "2",
"skirt_height": "3",
"min_skirt_length": "4",
"skirt_loops": "0",
"minimum_sparse_infill_area": "15",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "normal(auto)",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.2",
"support_bottom_z_distance": "0.2",
"support_filament": "0",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "2",
"support_interface_bottom_layers": "2",
"support_interface_spacing": "0.5",
"support_interface_speed": "80",
"support_base_pattern": "default",
"support_base_pattern_spacing": "2.5",
"support_speed": "150",
"support_threshold_angle": "30",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "30",
"tree_support_wall_count": "0",
"tree_support_with_infill": "0",
"detect_thin_wall": "0",
"top_surface_pattern": "monotonicline",
"top_shell_thickness": "0.8",
"enable_prime_tower": "0",
"wipe_tower_no_sparse_layers": "0",
"prime_tower_width": "60",
"xy_hole_compensation": "0",
"xy_contour_compensation": "0",
"layer_height": "0.2",
"bottom_shell_layers": "3",
"top_shell_layers": "4",
"bridge_flow": "1",
"initial_layer_speed": "45",
"initial_layer_infill_speed": "45",
"outer_wall_speed": "45",
"inner_wall_speed": "80",
"sparse_infill_speed": "150",
"internal_solid_infill_speed": "150",
"top_surface_speed": "50",
"gap_infill_speed": "30",
"travel_speed": "200"
}

View File

@@ -0,0 +1,109 @@
{
"type": "process",
"name": "fdm_process_lh_common",
"inherits": "fdm_process_common",
"from": "system",
"instantiation": "false",
"exclude_object": "1",
"accel_to_decel_enable": "0",
"bottom_shell_layers": "4",
"bridge_acceleration": "10000",
"bridge_density": "100%",
"brim_object_gap": "0.05",
"brim_width": "4",
"default_acceleration": "20000",
"dont_filter_internal_bridges": "limited",
"elefant_foot_compensation": "0.05",
"ensure_vertical_shell_thickness": "ensure_critical_only",
"filter_out_gap_fill": "1",
"gap_fill_target": "everywhere",
"gap_infill_speed": "400",
"independent_support_layer_height": "0",
"infill_jerk": "15",
"infill_wall_overlap": "15%",
"top_bottom_infill_wall_overlap": "22%",
"initial_layer_acceleration": "600",
"initial_layer_infill_speed": "140",
"initial_layer_jerk": "15",
"initial_layer_line_width": "0.5",
"initial_layer_speed": "60",
"initial_layer_travel_speed": "300",
"inner_wall_acceleration": "20000",
"inner_wall_jerk": "15",
"inner_wall_line_width": "0.4",
"inner_wall_speed": "400",
"internal_bridge_speed": "70",
"internal_solid_infill_acceleration": "20000",
"internal_solid_infill_line_width": "0.4",
"internal_solid_infill_speed": "400",
"ironing_flow": "19%",
"ironing_inset": "0.3",
"ironing_speed": "50",
"line_width": "0.4",
"min_bead_width": "75%",
"min_feature_size": "20%",
"min_length_factor": "1.5",
"min_width_top_surface": "200%",
"only_one_wall_top": "1",
"outer_wall_acceleration": "10000",
"outer_wall_jerk": "15",
"outer_wall_line_width": "0.4",
"outer_wall_speed": "400",
"overhang_1_4_speed": "70%",
"overhang_4_4_speed": "15",
"prime_tower_brim_width": "2",
"prime_tower_width": "80",
"prime_volume": "75",
"raft_first_layer_density": "70%",
"reduce_infill_retraction": "0",
"resolution": "0.01",
"role_based_wipe_speed": "0",
"seam_gap": "0",
"skirt_distance": "8",
"skirt_height": "1",
"skirt_speed": "100",
"skirt_start_angle": "-25",
"slice_closing_radius": "0.04",
"slowdown_for_curled_perimeters": "0",
"sparse_infill_acceleration": "20000",
"sparse_infill_density": "20%",
"sparse_infill_line_width": "0.4",
"sparse_infill_pattern": "3dhoneycomb",
"sparse_infill_speed": "400",
"support_angle": "135",
"support_base_pattern_spacing": "2",
"support_expansion": "1",
"support_interface_spacing": "0.3",
"support_interface_speed": "400",
"support_line_width": "0.4",
"support_object_xy_distance": "0.2",
"support_on_build_plate_only": "1",
"support_speed": "400",
"support_style": "snug",
"support_top_z_distance": "0.15",
"thick_internal_bridges": "0",
"top_shell_layers": "5",
"top_surface_acceleration": "10000",
"top_surface_jerk": "15",
"top_surface_line_width": "0.4",
"top_surface_speed": "250",
"travel_acceleration": "20000",
"travel_jerk": "15",
"travel_speed": "400",
"wall_generator": "classic",
"wall_loops": "2",
"wall_sequence": "outer wall/inner wall",
"wipe_speed": "150",
"wipe_tower_bridging": "15",
"wipe_tower_extra_flow": "120%",
"wipe_tower_max_purge_speed": "200",
"enable_prime_tower": "1",
"precise_outer_wall": "0",
"print_extruder_id": [
"1"
],
"brim_type": "auto_brim",
"print_extruder_variant": [
"Direct Drive Standard"
]
}

View File

@@ -132,6 +132,7 @@ def update_profile_library(vendor="",profile_type="filament"):
library[profile_section] = sorted_profiles
f.seek(0)
json.dump(library, f, indent="\t", ensure_ascii=False)
f.write('\n')
f.truncate()
print(f"Profile library for {vendor} updated successfully!")
@@ -230,6 +231,7 @@ def clean_up_profile(vendor="", profile_type="", force=False):
f.seek(0)
ordered_profile = create_ordered_profile(_profile, ['type', 'name', 'renamed_from', 'inherits', 'from', 'setting_id', 'filament_id', 'instantiation'])
json.dump(ordered_profile, f, indent="\t", ensure_ascii=False)
f.write('\n')
f.truncate()
print(f"Updated profile: {full_path}")
except Exception as e:
@@ -274,6 +276,7 @@ def rename_filament_system(vendor="OrcaFilamentLibrary"):
if modified:
with open(full_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent="\t", ensure_ascii=False)
f.write('\n')
print(f"Updated {full_path}")
except Exception as e:

View File

@@ -161,10 +161,11 @@ namespace AABBTreeLines {
// on centroids of the lines.
// Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies
// during tree traversal.
template <typename LineType>
inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(const std::vector<LineType>& lines)
template<typename LineType>
inline AABBTreeIndirect::Tree<LineType::Dim, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(
const std::vector<LineType>& lines)
{
using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>;
using TreeType = AABBTreeIndirect::Tree<LineType::Dim, typename LineType::Scalar>;
// using CoordType = typename TreeType::CoordType;
using VectorType = typename TreeType::VectorType;
using BoundingBox = typename TreeType::BoundingBox;
@@ -303,7 +304,7 @@ namespace AABBTreeLines {
private:
std::vector<LineType> lines;
AABBTreeIndirect::Tree<2, Scalar> tree;
AABBTreeIndirect::Tree<LineType::Dim, Scalar> tree;
public:
explicit LinesDistancer(const std::vector<LineType>& lines)
@@ -321,15 +322,15 @@ namespace AABBTreeLines {
LinesDistancer() = default;
// 1 true, -1 false, 0 cannot determine
int outside(const Vec<2, Scalar>& point) const { return point_outside_closed_contours(lines, tree, point); }
int outside(const Vec<LineType::Dim, Scalar>& point) const { return point_outside_closed_contours(lines, tree, point); }
// negative sign means inside
template <bool SIGNED_DISTANCE>
std::tuple<Floating, size_t, Vec<2, Floating>> distance_from_lines_extra(const Vec<2, Scalar>& point) const
template<bool SIGNED_DISTANCE>
std::tuple<Floating, size_t, Vec<LineType::Dim, Floating>> distance_from_lines_extra(const Vec<LineType::Dim, Scalar>& point) const
{
size_t nearest_line_index_out = size_t(-1);
Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero();
Vec<2, Floating> p = point.template cast<Floating>();
Vec<LineType::Dim, Floating> nearest_point_out = Vec<LineType::Dim, Floating>::Zero();
Vec<LineType::Dim, Floating> p = point.template cast<Floating>();
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out);
if (distance < 0) {
@@ -344,22 +345,20 @@ namespace AABBTreeLines {
return { distance, nearest_line_index_out, nearest_point_out };
}
template <bool SIGNED_DISTANCE>
Floating distance_from_lines(const Vec<2, typename LineType::Scalar>& point) const
template<bool SIGNED_DISTANCE> Floating distance_from_lines(const Vec<LineType::Dim, typename LineType::Scalar>& point) const
{
auto [dist, idx, np] = distance_from_lines_extra<SIGNED_DISTANCE>(point);
return dist;
}
std::vector<size_t> all_lines_in_radius(const Vec<2, Scalar> &point, Floating radius)
{
return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast<Floating>(), radius * radius);
}
template <bool sorted>
std::vector<std::pair<Vec<2, Scalar>, size_t>> intersections_with_line(const LineType& line) const
std::vector<size_t> all_lines_in_radius(const Vec<LineType::Dim, Scalar>& point, Floating radius)
{
return get_intersections_with_line<sorted, Vec<2, Scalar>>(lines, tree, line);
return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast<Floating>(), radius * radius);
}
template<bool sorted> std::vector<std::pair<Vec<LineType::Dim, Scalar>, size_t>> intersections_with_line(const LineType& line) const
{
return get_intersections_with_line<sorted, Vec<LineType::Dim, Scalar>>(lines, tree, line);
}
const LineType& get_line(size_t line_idx) const { return lines[line_idx]; }

View File

@@ -236,7 +236,18 @@ class BoundingBox3 : public BoundingBox3Base<Vec3crd>
public:
BoundingBox3() : BoundingBox3Base<Vec3crd>() {}
BoundingBox3(const Vec3crd &pmin, const Vec3crd &pmax) : BoundingBox3Base<Vec3crd>(pmin, pmax) {}
BoundingBox3(const Points3& points) : BoundingBox3Base<Vec3crd>(points) {}
BoundingBox3(const Points3& points) : BoundingBox3Base<Vec3crd>() {
if (!points.empty()) {
this->min = points.front();
this->max = points.front();
for (const auto &p : points) {
this->min = this->min.cwiseMin(static_cast<const Vec3crd&>(p));
this->max = this->max.cwiseMax(static_cast<const Vec3crd&>(p));
}
this->defined = true;
}
}
BoundingBox3(const std::vector<Vec3crd>& points) : BoundingBox3Base<Vec3crd>(points) {}
};
class BoundingBoxf : public BoundingBoxBase<Vec2d>

View File

@@ -100,6 +100,7 @@ set(lisbslic3r_sources
CommonDefs.hpp
Config.cpp
Config.hpp
ContourZ.cpp
CustomGCode.cpp
CustomGCode.hpp
CutUtils.cpp

View File

@@ -3,6 +3,7 @@
#include <cmath>
#include <cassert>
#include "Geometry.hpp"
#include "Polygon.hpp"
//BBS: Refer to ArcWelderLib for the arc fitting functions
@@ -94,6 +95,12 @@ bool Circle::try_create_circle(const Points& points, const double max_radius, co
return found_circle;
}
bool Circle::try_create_circle(const Points3& points, const double max_radius, const double tolerance, Circle& new_circle)
{
return Circle::try_create_circle(to_points(points), max_radius, tolerance, new_circle);
}
double Circle::get_polar_radians(const Point& p1) const
{
double polar_radians = atan2(p1.y() - center.y(), p1.x() - center.x());
@@ -291,6 +298,31 @@ bool ArcSegment::try_create_arc(
return false;
}
bool ArcSegment::try_create_arc(
const Points3& points,
ArcSegment& target_arc,
double approximate_length,
double max_radius,
double tolerance,
double path_tolerance_percent)
{
Circle test_circle = (Circle)target_arc;
if (!Circle::try_create_circle(points, max_radius, tolerance, test_circle))
return false;
int mid_point_index = ((points.size() - 2) / 2) + 1;
ArcSegment test_arc;
if (!ArcSegment::try_create_arc(test_circle, points[0].to_point(), points[mid_point_index].to_point(), points[points.size() - 1].to_point(), test_arc, approximate_length, path_tolerance_percent))
return false;
if (ArcSegment::are_points_within_slice(test_arc, points))
{
target_arc = test_arc;
return true;
}
return false;
}
bool ArcSegment::try_create_arc(
const Circle& c,
const Point& start_point,
@@ -455,6 +487,87 @@ bool ArcSegment::are_points_within_slice(const ArcSegment& test_arc, const Point
return true;
}
bool ArcSegment::are_points_within_slice(const ArcSegment& test_arc, const Points3& points)
{
//BBS: Check all the points and see if they fit inside of the angles
double previous_polar = test_arc.polar_start_theta;
bool will_cross_zero = false;
bool crossed_zero = false;
const int point_count = points.size();
Vec2d start_norm(((double)test_arc.start_point.x() - (double)test_arc.center.x()) / test_arc.radius,
((double)test_arc.start_point.y() - (double)test_arc.center.y()) / test_arc.radius);
Vec2d end_norm(((double)test_arc.end_point.x() - (double)test_arc.center.x()) / test_arc.radius,
((double)test_arc.end_point.y() - (double)test_arc.center.y()) / test_arc.radius);
if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
will_cross_zero = test_arc.polar_start_theta > test_arc.polar_end_theta;
else
will_cross_zero = test_arc.polar_start_theta < test_arc.polar_end_theta;
//BBS: check if point 1 to point 2 cross zero
double polar_test;
for (int index = point_count - 2; index < point_count; index++)
{
if (index < point_count - 1)
polar_test = test_arc.get_polar_radians(points[index].to_point());
else
polar_test = test_arc.polar_end_theta;
//BBS: First ensure the test point is within the arc
if (test_arc.direction == ArcDirection::Arc_Dir_CCW)
{
//BBS: Only check to see if we are within the arc if this isn't the endpoint
if (index < point_count - 1) {
if (will_cross_zero) {
if (!(polar_test > test_arc.polar_start_theta || polar_test < test_arc.polar_end_theta))
return false;
} else if (!(test_arc.polar_start_theta < polar_test && polar_test < test_arc.polar_end_theta))
return false;
}
//BBS: check the angles are increasing
if (previous_polar > polar_test) {
if (!will_cross_zero)
return false;
//BBS: Allow the angle to cross zero once
if (crossed_zero)
return false;
crossed_zero = true;
}
} else {
if (index < point_count - 1) {
if (will_cross_zero) {
if (!(polar_test < test_arc.polar_start_theta || polar_test > test_arc.polar_end_theta))
return false;
} else if (!(test_arc.polar_start_theta > polar_test && polar_test > test_arc.polar_end_theta))
return false;
}
//BBS: Now make sure the angles are decreasing
if (previous_polar < polar_test)
{
if (!will_cross_zero)
return false;
//BBS: Allow the angle to cross zero once
if (crossed_zero)
return false;
crossed_zero = true;
}
}
// BBS: check if the segment intersects either of the vector from the center of the circle to the endpoints of the arc
Line segmemt(points[index - 1].to_point(), points[index].to_point());
if ((index != 1 && ray_intersects_segment(test_arc.center, start_norm, segmemt)) ||
(index != point_count - 1 && ray_intersects_segment(test_arc.center, end_norm, segmemt)))
return false;
previous_polar = polar_test;
}
//BBS: Ensure that all arcs that cross zero
if (will_cross_zero != crossed_zero)
return false;
return true;
}
// BBS: this function is used to detect whether a ray cross the segment
bool ArcSegment::ray_intersects_segment(const Point &rayOrigin, const Vec2d &rayDirection, const Line& segment)
{

View File

@@ -28,6 +28,7 @@ public:
static bool try_create_circle(const Point &p1, const Point &p2, const Point &p3, const double max_radius, Circle& new_circle);
static bool try_create_circle(const Points& points, const double max_radius, const double tolerance, Circle& new_circle);
static bool try_create_circle(const Points3& points, const double max_radius, const double tolerance, Circle& new_circle);
double get_polar_radians(const Point& p1) const;
bool is_over_deviation(const Points& points, const double tolerance);
bool get_deviation_sum_squared(const Points& points, const double tolerance, double& sum_deviation);
@@ -111,8 +112,16 @@ public:
double max_radius = DEFAULT_SCALED_MAX_RADIUS,
double tolerance = DEFAULT_SCALED_RESOLUTION,
double path_tolerance_percent = DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE);
static bool try_create_arc(
const Points3 &points,
ArcSegment& target_arc,
double approximate_length,
double max_radius = DEFAULT_SCALED_MAX_RADIUS,
double tolerance = DEFAULT_SCALED_RESOLUTION,
double path_tolerance_percent = DEFAULT_ARC_LENGTH_PERCENT_TOLERANCE);
static bool are_points_within_slice(const ArcSegment& test_arc, const Points &points);
static bool are_points_within_slice(const ArcSegment& test_arc, const Points3 &points);
// BBS: this function is used to detect whether a ray cross the segment
static bool ray_intersects_segment(const Point& rayOrigin, const Vec2d& rayDirection, const Line& segment);
// BBS: these three functions are used to calculate related arguments of arc in unscale_field.

View File

@@ -411,6 +411,19 @@ Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta
Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::EndType end_type)
{ assert(delta > 0); return to_polygons(clipper_union<ClipperLib::Paths>(raw_offset_polyline(ClipperUtils::SinglePathProvider(polyline.points), delta, joinType, miterLimit, end_type))); }
Slic3r::Polygons offset(const Slic3r::Polyline3 &polyline, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::EndType end_type)
{
assert(delta > 0);
return to_polygons(
clipper_union<ClipperLib::Paths>(
raw_offset_polyline(
ClipperUtils::SinglePathProvider(polyline.to_polyline().points),
delta,
joinType,
miterLimit,
end_type)));
}
Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::EndType end_type)
{ assert(delta > 0); return to_polygons(clipper_union<ClipperLib::Paths>(raw_offset_polyline(ClipperUtils::PolylinesProvider(polylines), delta, joinType, miterLimit, end_type))); }

View File

@@ -334,6 +334,7 @@ Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, Clipp
// Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better.
// Input polygons for negative offset shall be "normalized": There must be no overlap / intersections between the input polygons.
Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = DefaultLineJoinType, double miterLimit = DefaultLineMiterLimit, ClipperLib::EndType end_type = DefaultEndType);
Slic3r::Polygons offset(const Slic3r::Polyline3 &polyline, const float delta, ClipperLib::JoinType joinType = DefaultLineJoinType, double miterLimit = DefaultLineMiterLimit, ClipperLib::EndType end_type = DefaultEndType);
Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, ClipperLib::JoinType joinType = DefaultLineJoinType, double miterLimit = DefaultLineMiterLimit, ClipperLib::EndType end_type = DefaultEndType);
Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit);
Slic3r::Polygons offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit);
@@ -524,6 +525,8 @@ Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip);
Slic3r::Polylines3 intersection_pl(const Slic3r::Polylines3 &subject, const Slic3r::Polygon &clip);
Slic3r::Polylines3 intersection_pl(const Slic3r::Polylines3 &subject, const Slic3r::ExPolygon &clip);
inline Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
{

236
src/libslic3r/ContourZ.cpp Normal file
View File

@@ -0,0 +1,236 @@
#include "Exception.hpp"
#include "ExtrusionEntity.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "Layer.hpp"
#include "Point.hpp"
#include "Print.hpp"
#include "SLA/IndexedMesh.hpp"
#include "libslic3r.h"
#include <cfloat>
#include <cmath>
#include <initializer_list>
#include <string>
namespace Slic3r {
static void contour_extrusion_entity(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntity *extr);
static double follow_slope_down(double angle_rad, double dist)
{
return -dist * std::sin(angle_rad);
}
static double slope_from_normal(const Eigen::Vector3d& normal)
{
// Ensure the normal is normalized
Eigen::Vector3d n = normal.normalized();
// Compute angle between normal and z-axis
double angle_rad = std::acos(std::abs(n.z())); // angle between normal and vertical
return angle_rad;
}
static bool contour_extrusion_path(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionPath &path)
{
if (path.role() != erTopSolidInfill && path.role() != erIroning && path.role() != erExternalPerimeter && path.role() != erPerimeter) {
return false;
}
Layer *layer = region->layer();
coordf_t mesh_z = layer->print_z + mesh.ground_level();
coordf_t min_z = region->region().config().zaa_min_z;
const Points3 &points = path.polyline.points;
double resolution_mm = 0.1;
coordf_t height = layer->height;
double minimize_perimeter_height_angle = region->region().config().zaa_minimize_perimeter_height;
Pointf3s contoured_points;
bool was_contoured = false;
for (Points3::const_iterator it = points.begin(); it != points.end()-1; ++it) {
Vec2d p1d(unscale_(it->x()), unscale_(it->y()));
Vec2d p2d(unscale_((it+1)->x()), unscale_((it+1)->y()));
Linef line(p1d, p2d);
double length_mm = line.length();
int num_segments = int(std::ceil(length_mm / resolution_mm));
Vec2d delta = line.vector();
if (num_segments == 0) {
continue;
}
for (int i = 0; i < num_segments + 1; i++) {
Vec2d p = p1d + delta * i / num_segments;
coordf_t x = p.x();
coordf_t y = p.y();
sla::IndexedMesh::hit_result hit_up = mesh.query_ray_hit({x, y, mesh_z}, {0.0, 0.0, 1.0});
sla::IndexedMesh::hit_result hit_down = mesh.query_ray_hit({x, y, mesh_z}, {0.0, 0.0, -1.0});
double up = hit_up.distance();
double down = hit_down.distance();
double d = up < down ? up : -down;
const Vec3d &normal = (up < down ? hit_up : hit_down).normal();
double max_up = min_z;
double min_down = -(height - min_z);
double half_width = path.width / 2.0;
if (path.role() == erIroning) {
max_up = height;
min_down = -(height + 0.1);
}
if (is_perimeter(path.role())) {
double slope_rad = slope_from_normal(normal);
double slope_degrees = slope_rad * 180.0 / M_PI;
if (d > min_down && minimize_perimeter_height_angle > 0 && minimize_perimeter_height_angle < slope_degrees) {
double adjustment = follow_slope_down(slope_rad, half_width);
if (adjustment > 0) {
throw RuntimeError("ContourZ: got positive adjustment");
}
d += adjustment;
if (d < min_down) {
d = min_down;
}
}
}
if (d < -height || d > max_up + 0.03) {
// this point is too far from the mesh edge, probably because this is not a top surface. Do not contour it.
d = 0;
}
if (d < min_down) {
d = min_down;
} else if (d > max_up) {
d = max_up;
}
if (is_perimeter(path.role()) && d > 0) {
// do not increase height of perimeters as this may create an appearance of a seam
d = 0;
}
if (std::abs(d) > EPSILON) {
was_contoured = true;
}
Vec3d new_point = {p.x(), p.y(), d};
if (contoured_points.size() >= 2) {
double dist = Linef3::distance_to_infinite_squared(new_point, contoured_points[contoured_points.size() - 2],
contoured_points[contoured_points.size() - 1]);
if (dist < EPSILON * EPSILON) {
contoured_points[contoured_points.size() - 1] = new_point;
continue;
}
}
contoured_points.push_back(new_point);
}
}
if (!was_contoured) {
return false;
}
Polyline3 polyline;
for (const Vec3d &point : contoured_points) {
polyline.append(Point3(scale_(point.x()), scale_(point.y()), scale_(point.z())));
}
path.polyline = std::move(polyline);
path.z_contoured = true;
return true;
}
static void contour_extrusion_multipath(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionMultiPath &multipath)
{
for (ExtrusionPath &path : multipath.paths) {
contour_extrusion_path(region, mesh, path);
}
}
static void contour_extrusion_loop(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionLoop &loop)
{
for (ExtrusionPath &path : loop.paths) {
contour_extrusion_path(region, mesh, path);
}
}
static void contour_extrusion_entitiy_collection(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntityCollection &collection)
{
for (ExtrusionEntity *entity : collection.entities) {
contour_extrusion_entity(region, mesh, entity);
}
}
static void contour_extrusion_entity(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntity *extr)
{
const ExtrusionPathSloped *sloped = dynamic_cast<const ExtrusionPathSloped*>(extr);
if (sloped != nullptr) {
throw RuntimeError("ExtrusionPathSloped not implemented");
return;
}
ExtrusionMultiPath *multipath = dynamic_cast<ExtrusionMultiPath*>(extr);
if (multipath != nullptr) {
contour_extrusion_multipath(region, mesh, *multipath);
return;
}
ExtrusionPath *path = dynamic_cast<ExtrusionPath*>(extr);
if (path != nullptr) {
contour_extrusion_path(region, mesh, *path);
return;
}
ExtrusionLoop *loop = dynamic_cast<ExtrusionLoop*>(extr);
if (loop != nullptr) {
contour_extrusion_loop(region, mesh, *loop);
return;
}
const ExtrusionLoopSloped *loop_sloped = dynamic_cast<const ExtrusionLoopSloped*>(extr);
if (loop_sloped != nullptr) {
throw RuntimeError("ExtrusionLoopSloped not implemented");
return;
}
ExtrusionEntityCollection *collection = dynamic_cast<ExtrusionEntityCollection*>(extr);
if (collection != nullptr) {
contour_extrusion_entitiy_collection(region, mesh, *collection);
return;
}
throw RuntimeError("ContourZ: ExtrusionEntity type not implemented: " + std::string(typeid(*extr).name()));
return;
}
static void handle_extrusion_collection(LayerRegion *region, const sla::IndexedMesh &mesh, ExtrusionEntityCollection &collection, std::initializer_list<ExtrusionRole> roles) {
for (ExtrusionEntity* extr : collection.entities) {
if (!contains(roles, extr->role())) {
continue;
}
contour_extrusion_entity(region, mesh, extr);
}
}
void Layer::make_contour_z(const sla::IndexedMesh &mesh)
{
for (LayerRegion *region : this->regions()) {
if (!region->region().config().zaa_enabled)
continue;
handle_extrusion_collection(region, mesh, region->fills, {erTopSolidInfill, erIroning, erPerimeter, erExternalPerimeter, erMixed});
handle_extrusion_collection(region, mesh, region->perimeters, {erPerimeter, erExternalPerimeter, erMixed});
}
}
} // namespace Slic3r

View File

@@ -192,6 +192,25 @@ inline Linesf to_unscaled_linesf(const ExPolygons &src)
return lines;
}
inline Linesf3 to_unscaled_linesf3(const ExPolygons& src)
{
Linesf3 lines;
lines.reserve(count_points(src));
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++it_expoly) {
for (size_t i = 0; i <= it_expoly->holes.size(); ++i) {
const Points& points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points;
Vec2d unscaled_a = unscaled(points.front());
Vec2d unscaled_b = unscaled_a;
for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) {
unscaled_b = unscaled(*(it));
lines.push_back(Linef3(unscaled_a, unscaled_b, 0));
unscaled_a = unscaled_b;
}
lines.push_back(Linef3(unscaled_a, unscaled(points.front()), 0));
}
}
return lines;
}
inline Points to_points(const ExPolygons &src)
{

View File

@@ -17,12 +17,12 @@ static const double slope_inner_outer_wall_gap = 0.4;
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection), retval);
this->_inflate_collection(intersection_pl(Polylines{ polyline.to_polyline() }, collection), retval);
}
void ExtrusionPath::subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection), retval);
this->_inflate_collection(diff_pl(Polylines{ this->polyline.to_polyline() }, collection), retval);
}
void ExtrusionPath::clip_end(double distance)
@@ -32,11 +32,17 @@ void ExtrusionPath::clip_end(double distance)
void ExtrusionPath::simplify(double tolerance)
{
if (this->z_contoured) {
return;
}
this->polyline.simplify(tolerance);
}
void ExtrusionPath::simplify_by_fitting_arc(double tolerance)
{
if (this->z_contoured) {
return;
}
this->polyline.simplify_by_fitting_arc(tolerance);
}
@@ -45,15 +51,23 @@ double ExtrusionPath::length() const
return this->polyline.length();
}
void ExtrusionPath::collect_points(Points &dst) const
{
dst.reserve(dst.size() + this->polyline.points.size());
for (const Point3 &point : this->polyline.points) {
dst.emplace_back(point.x(), point.y());
}
}
void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
{
for (const Polyline &polyline : polylines)
collection->entities.emplace_back(new ExtrusionPath(polyline, *this));
collection->entities.emplace_back(new ExtrusionPath(Polyline3(polyline), *this));
}
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
polygons_append(out, offset(this->polyline, float(scale_(this->width/2)) + scaled_epsilon));
polygons_append(out, offset(this->polyline.to_polyline(), float(scale_(this->width/2)) + scaled_epsilon));
}
void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
@@ -64,7 +78,7 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
// SoftFever: TODO Mac trigger assersion errors
// assert(! bridge || this->width == this->height);
auto flow = bridge ? Flow::bridging_flow(this->width, 0.f) : Flow(this->width, this->height, 0.f);
polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
polygons_append(out, offset(this->polyline.to_polyline(), 0.5f * float(flow.scaled_spacing()) + scaled_epsilon));
}
void ExtrusionMultiPath::reverse()
@@ -116,9 +130,10 @@ Polyline ExtrusionMultiPath::as_polyline() const
len -= paths.size() - 1;
assert(len > 0);
out.points.reserve(len);
out.points.push_back(paths.front().polyline.points.front());
out.points.push_back(paths.front().polyline.points.front().to_point());
for (size_t i_path = 0; i_path < paths.size(); ++ i_path)
out.points.insert(out.points.end(), paths[i_path].polyline.points.begin() + 1, paths[i_path].polyline.points.end());
for (auto it = paths[i_path].polyline.points.begin() + 1; it != paths[i_path].polyline.points.end(); ++it)
out.points.push_back(it->to_point());
}
return out;
}
@@ -149,7 +164,9 @@ Polygon ExtrusionLoop::polygon() const
Polygon polygon;
for (const ExtrusionPath &path : this->paths) {
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
polygon.points.insert(polygon.points.end(), path.polyline.points.begin(), path.polyline.points.end()-1);
for (auto it = path.polyline.points.begin(); it != path.polyline.points.end() - 1; ++it) {
polygon.points.push_back(it->to_point());
}
}
return polygon;
}
@@ -168,7 +185,7 @@ bool ExtrusionLoop::split_at_vertex(const Point &point, const double scaled_epsi
if (int idx = path->polyline.find_point(point, scaled_epsilon); idx != -1) {
if (this->paths.size() == 1) {
// just change the order of points
Polyline p1, p2;
Polyline3 p1, p2;
path->polyline.split_at_index(idx, &p1, &p2);
if (p1.is_valid() && p2.is_valid()) {
p2.append(std::move(p1));
@@ -178,7 +195,7 @@ bool ExtrusionLoop::split_at_vertex(const Point &point, const double scaled_epsi
} else {
// new paths list starts with the second half of current path
ExtrusionPaths new_paths;
Polyline p1, p2;
Polyline3 p1, p2;
path->polyline.split_at_index(idx, &p1, &p2);
new_paths.reserve(this->paths.size() + 1);
{
@@ -218,16 +235,17 @@ ExtrusionLoop::ClosestPathPoint ExtrusionLoop::get_closest_path_and_point(const
ClosestPathPoint best_non_overhang{0, 0};
double min2_non_overhang = std::numeric_limits<double>::max();
for (const ExtrusionPath &path : this->paths) {
std::pair<int, Point> foot_pt_ = foot_pt(path.polyline.points, point);
double d2 = (foot_pt_.second - point).cast<double>().squaredNorm();
std::pair<int, Point3> foot_pt_ = foot_pt(path.polyline.points, Point3(point));
Point foot_pt_2d = Point(foot_pt_.second.x(), foot_pt_.second.y());
double d2 = (foot_pt_2d - point).cast<double>().squaredNorm();
if (d2 < min2) {
out.foot_pt = foot_pt_.second;
out.foot_pt = foot_pt_2d;
out.path_idx = &path - &this->paths.front();
out.segment_idx = foot_pt_.first;
min2 = d2;
}
if (prefer_non_overhang && !is_bridge(path.role()) && d2 < min2_non_overhang) {
best_non_overhang.foot_pt = foot_pt_.second;
best_non_overhang.foot_pt = foot_pt_2d;
best_non_overhang.path_idx = &path - &this->paths.front();
best_non_overhang.segment_idx = foot_pt_.first;
min2_non_overhang = d2;
@@ -249,16 +267,18 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const
// Snap p to start or end of segment_idx if closer than scaled_epsilon.
{
const Point *p1 = this->paths[path_idx].polyline.points.data() + segment_idx;
const Point *p2 = p1;
const Point3 *p1 = this->paths[path_idx].polyline.points.data() + segment_idx;
const Point3 *p2 = p1;
++p2;
double d2_1 = (point - *p1).cast<double>().squaredNorm();
double d2_2 = (point - *p2).cast<double>().squaredNorm();
Point p1_2d = Point(p1->x(), p1->y());
Point p2_2d = Point(p2->x(), p2->y());
double d2_1 = (point - p1_2d).cast<double>().squaredNorm();
double d2_2 = (point - p2_2d).cast<double>().squaredNorm();
const double thr2 = scaled_epsilon * scaled_epsilon;
if (d2_1 < d2_2) {
if (d2_1 < thr2) p = *p1;
if (d2_1 < thr2) p = p1_2d;
} else {
if (d2_2 < thr2) p = *p2;
if (d2_2 < thr2) p = p2_2d;
}
}
@@ -266,8 +286,9 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const
const ExtrusionPath &path = this->paths[path_idx];
ExtrusionPath p1(path.role(), path.mm3_per_mm, path.width, path.height);
ExtrusionPath p2(path.role(), path.mm3_per_mm, path.width, path.height);
p1.z_contoured = p2.z_contoured = path.z_contoured;
path.polyline.split_at(p, &p1.polyline, &p2.polyline);
if (this->paths.size() == 1) {
if (!p1.polyline.is_valid()) {
std::swap(this->paths.front().polyline.points, p2.polyline.points);
@@ -411,16 +432,16 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths,
: ExtrusionLoop(role)
{
// create slopes
const auto add_slop = [this, slope_max_segment_length, seam_gap](const ExtrusionPath &path, const Polyline &poly, double ratio_begin, double ratio_end) {
const auto add_slop = [this, slope_max_segment_length, seam_gap](const ExtrusionPath &path, const Polyline3 &poly, double ratio_begin, double ratio_end) {
if (poly.empty()) { return; }
// Ensure `slope_max_segment_length`
Polyline detailed_poly;
Polyline3 detailed_poly;
{
detailed_poly.append(poly.first_point());
// Recursively split the line into half until no longer than `slope_max_segment_length`
const std::function<void(const Line &)> handle_line = [slope_max_segment_length, &detailed_poly, &handle_line](const Line &line) {
const std::function<void(const Line3 &)> handle_line = [slope_max_segment_length, &detailed_poly, &handle_line](const Line3 &line) {
if (line.length() <= slope_max_segment_length) {
detailed_poly.append(line.b);
} else {
@@ -441,8 +462,8 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths,
const auto seg_length = detailed_poly.length();
if (seg_length > seam_gap) {
// Split the segment and remove the last `seam_gap` bit
const Polyline orig = detailed_poly;
Polyline tmp;
const Polyline3 orig = detailed_poly;
Polyline3 tmp;
orig.split_at_length(seg_length - seam_gap, &detailed_poly, &tmp);
ratio_end = lerp(ratio_begin, ratio_end, (seg_length - seam_gap) / seg_length);
@@ -464,8 +485,8 @@ ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths,
const double path_len = unscale_(path->length());
if (path_len > remaining_length) {
// Split current path into slope and non-slope part
Polyline slope_path;
Polyline flat_path;
Polyline3 slope_path;
Polyline3 flat_path;
path->polyline.split_at_length(scale_(remaining_length), &slope_path, &flat_path);
add_slop(*path, slope_path, start_ratio, 1);
@@ -631,4 +652,28 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
return erNone;
}
// ExtrusionPathContoured implementation
ExtrusionEntity *ExtrusionPathContoured::clone() const {
return new ExtrusionPathContoured(*this);
}
ExtrusionEntity *ExtrusionPathContoured::clone_move() {
return new ExtrusionPathContoured(std::move(*this));
}
void ExtrusionPathContoured::simplify(double tolerance) {
// Do not simplify contoured paths
return;
}
void ExtrusionPathContoured::simplify_by_fitting_arc(double tolerance) {
// Do not simplify contoured paths
return;
}
void ExtrusionPathContoured::reverse() {
this->polyline.reverse();
std::reverse(this->z_diffs.begin(), this->z_diffs.end());
}
}

View File

@@ -116,8 +116,8 @@ public:
virtual ExtrusionEntity* clone_move() = 0;
virtual ~ExtrusionEntity() {}
virtual void reverse() = 0;
virtual const Point& first_point() const = 0;
virtual const Point& last_point() const = 0;
virtual Point first_point() const = 0;
virtual Point last_point() const = 0;
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
virtual void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const = 0;
@@ -150,13 +150,17 @@ typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
class ExtrusionPath : public ExtrusionEntity
{
public:
Polyline polyline;
Polyline3 polyline;
double overhang_degree = 0;
int curve_degree = 0;
// Volumetric velocity. mm^3 of plastic per mm of linear head motion. Used by the G-code generator.
double mm3_per_mm;
// Width of the extrusion, used for visualization purposes.
float width;
// Height of the extrusion, used for visualization purposes.
float height;
double smooth_speed = 0;
bool z_contoured = false;
ExtrusionPath() : mm3_per_mm(-1), width(-1), height(-1), m_role(erNone), m_no_extrusion(false) {}
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {}
@@ -164,36 +168,52 @@ public:
ExtrusionPath(const ExtrusionPath &rhs)
: polyline(rhs.polyline)
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
, smooth_speed(rhs.smooth_speed)
, z_contoured(rhs.z_contoured)
, m_can_reverse(rhs.m_can_reverse)
, m_role(rhs.m_role)
, m_no_extrusion(rhs.m_no_extrusion)
{}
ExtrusionPath(ExtrusionPath &&rhs)
: polyline(std::move(rhs.polyline))
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
, smooth_speed(rhs.smooth_speed)
, z_contoured(rhs.z_contoured)
, m_can_reverse(rhs.m_can_reverse)
, m_role(rhs.m_role)
, m_no_extrusion(rhs.m_no_extrusion)
{}
ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs)
ExtrusionPath(const Polyline3 &polyline, const ExtrusionPath &rhs)
: polyline(polyline)
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
, smooth_speed(rhs.smooth_speed)
, z_contoured(rhs.z_contoured)
, m_can_reverse(rhs.m_can_reverse)
, m_role(rhs.m_role)
, m_no_extrusion(rhs.m_no_extrusion)
{}
ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs)
ExtrusionPath(Polyline3 &&polyline, const ExtrusionPath &rhs)
: polyline(std::move(polyline))
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
, smooth_speed(rhs.smooth_speed)
, z_contoured(rhs.z_contoured)
, m_can_reverse(rhs.m_can_reverse)
, m_role(rhs.m_role)
, m_no_extrusion(rhs.m_no_extrusion)
@@ -206,6 +226,10 @@ public:
this->mm3_per_mm = rhs.mm3_per_mm;
this->width = rhs.width;
this->height = rhs.height;
this->smooth_speed = rhs.smooth_speed;
this->z_contoured = rhs.z_contoured;
this->overhang_degree = rhs.overhang_degree;
this->curve_degree = rhs.curve_degree;
this->polyline = rhs.polyline;
return *this;
}
@@ -216,6 +240,10 @@ public:
this->mm3_per_mm = rhs.mm3_per_mm;
this->width = rhs.width;
this->height = rhs.height;
this->smooth_speed = rhs.smooth_speed;
this->z_contoured = rhs.z_contoured;
this->overhang_degree = rhs.overhang_degree;
this->curve_degree = rhs.curve_degree;
this->polyline = std::move(rhs.polyline);
return *this;
}
@@ -224,8 +252,10 @@ public:
// Create a new object, initialize it with this object using the move semantics.
ExtrusionEntity* clone_move() override { return new ExtrusionPath(std::move(*this)); }
void reverse() override { this->polyline.reverse(); }
const Point& first_point() const override { return this->polyline.points.front(); }
const Point& last_point() const override { return this->polyline.points.back(); }
Point first_point() const override { return this->polyline.points.front().to_point(); }
Point3 first_point3() const { return this->polyline.points.front(); }
Point last_point() const override { return this->polyline.points.back().to_point(); }
Point3 last_point3() const { return this->polyline.points.back(); }
size_t size() const { return this->polyline.size(); }
bool empty() const { return this->polyline.empty(); }
bool is_closed() const { return ! this->empty() && this->polyline.points.front() == this->polyline.points.back(); }
@@ -236,7 +266,7 @@ public:
// Currently not used.
void subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const;
void clip_end(double distance);
void simplify(double tolerance);
virtual void simplify(double tolerance);
double length() const override;
ExtrusionRole role() const override { return m_role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
@@ -252,9 +282,10 @@ public:
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
double min_mm3_per_mm() const override { return this->mm3_per_mm; }
Polyline as_polyline() const override { return this->polyline; }
void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline); }
void collect_points(Points &dst) const override { append(dst, this->polyline.points); }
Polyline as_polyline() const override { return this->polyline.to_polyline(); }
void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline.to_polyline()); }
void collect_points(Points &dst) const override;
void collect_points3(Points3 &dst) const { append(dst, this->polyline.points); }
double total_volume() const override { return mm3_per_mm * unscale<double>(length()); }
//BBS: add new simplifing method by fitting arc
@@ -274,6 +305,23 @@ private:
bool m_no_extrusion = false;
};
class ExtrusionPathContoured : public ExtrusionPath {
public:
std::vector<double> z_diffs;
ExtrusionPathContoured(Polyline3 &&polyline, const ExtrusionPath &rhs, std::vector<double> &&z_diffs)
: ExtrusionPath(std::move(polyline), rhs), z_diffs(std::move(z_diffs))
{}
virtual ExtrusionEntity *clone() const override;
virtual ExtrusionEntity *clone_move() override;
void simplify(double tolerance) override;
virtual void simplify_by_fitting_arc(double tolerance);
void reverse() override;
};
class ExtrusionPathSloped : public ExtrusionPath
{
public:
@@ -292,10 +340,10 @@ public:
ExtrusionPathSloped(ExtrusionPath&& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(std::move(rhs)), slope_begin(begin), slope_end(end)
{}
ExtrusionPathSloped(const Polyline& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
ExtrusionPathSloped(const Polyline3& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(polyline, rhs), slope_begin(begin), slope_end(end)
{}
ExtrusionPathSloped(Polyline&& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
ExtrusionPathSloped(Polyline3&& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(std::move(polyline), rhs), slope_begin(begin), slope_end(end)
{}
@@ -354,8 +402,8 @@ public:
// Create a new object, initialize it with this object using the move semantics.
ExtrusionEntity* clone_move() override { return new ExtrusionMultiPath(std::move(*this)); }
void reverse() override;
const Point& first_point() const override { return this->paths.front().polyline.points.front(); }
const Point& last_point() const override { return this->paths.back().polyline.points.back(); }
Point first_point() const override { return this->paths.front().polyline.points.front().to_point(); }
Point last_point() const override { return this->paths.back().polyline.points.back().to_point(); }
size_t size() const { return this->paths.size(); }
bool empty() const { return this->paths.empty(); }
double length() const override;
@@ -379,7 +427,7 @@ public:
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
dst.reserve(dst.size() + n);
for (const ExtrusionPath &p : this->paths)
append(dst, p.polyline.points);
append(dst, to_points(p.polyline.points));
}
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
@@ -410,8 +458,8 @@ public:
bool is_clockwise() { return this->polygon().is_clockwise(); }
bool is_counter_clockwise() { return this->polygon().is_counter_clockwise(); }
void reverse() override;
const Point& first_point() const override { return this->paths.front().polyline.points.front(); }
const Point& last_point() const override { assert(this->first_point() == this->paths.back().polyline.points.back()); return this->first_point(); }
Point first_point() const override { return this->paths.front().polyline.points.front().to_point(); }
Point last_point() const override { assert(this->first_point() == this->paths.back().polyline.points.back().to_point()); return this->first_point(); }
Polygon polygon() const;
double length() const override;
bool split_at_vertex(const Point &point, const double scaled_epsilon = scaled<double>(0.001));
@@ -443,13 +491,17 @@ public:
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
double min_mm3_per_mm() const override;
Polyline as_polyline() const override { return this->polygon().split_at_first_point(); }
Polyline as_polyline() const override {
if (this->paths.empty() || this->length() <= 0.)
return Polyline();
return this->polygon().split_at_first_point();
}
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
void collect_points(Points &dst) const override {
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
dst.reserve(dst.size() + n);
for (const ExtrusionPath &p : this->paths)
append(dst, p.polyline.points);
append(dst, to_points(p.polyline.points));
}
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
// check if the loop is smooth, angle_threshold is in radians, default is 10 degrees
@@ -495,7 +547,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, Ex
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = polyline;
dst.back().polyline = Polyline3(polyline);
}
}
@@ -505,7 +557,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = std::move(polyline);
dst.back().polyline = Polyline3(std::move(polyline));
}
polylines.clear();
}
@@ -515,7 +567,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polyline &&polyline, Ext
dst.reserve(dst.size() + 1);
if (polyline.is_valid()) {
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = std::move(polyline);
dst.back().polyline = Polyline3(std::move(polyline));
}
}
@@ -526,7 +578,7 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines
if (polyline.is_valid()) {
ExtrusionPath *extrusion_path = can_reverse ? new ExtrusionPath(role, mm3_per_mm, width, height) : new ExtrusionPathOriented(role, mm3_per_mm, width, height);
dst.push_back(extrusion_path);
extrusion_path->polyline = polyline;
extrusion_path->polyline = Polyline3(polyline);
}
}
@@ -537,7 +589,7 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines
if (polyline.is_valid()) {
ExtrusionPath *extrusion_path = can_reverse ? new ExtrusionPath(role, mm3_per_mm, width, height) : new ExtrusionPathOriented(role, mm3_per_mm, width, height);
dst.push_back(extrusion_path);
extrusion_path->polyline = std::move(polyline);
extrusion_path->polyline = Polyline3(std::move(polyline));
}
polylines.clear();
}
@@ -557,7 +609,7 @@ inline void extrusion_entities_append_paths_with_wipe(ExtrusionEntitiesPtr &dst,
Point temp = polyline.first_point() - last_end_point;
if (Vec2d(temp.x(), temp.y()).norm() <= 3 * scaled(width)) {
multi_path->paths.emplace_back(role, mm3_per_mm, width, height, true);
multi_path->paths.back().polyline = std::move(Polyline(last_end_point, polyline.first_point()));
multi_path->paths.back().polyline = Polyline3(Polyline(last_end_point, polyline.first_point()));
} else {
dst.push_back(multi_path);
multi_path = new ExtrusionMultiPath();
@@ -565,9 +617,9 @@ inline void extrusion_entities_append_paths_with_wipe(ExtrusionEntitiesPtr &dst,
}
multi_path->paths.emplace_back(role, mm3_per_mm, width, height);
multi_path->paths.back().polyline = std::move(polyline);
multi_path->paths.back().polyline = Polyline3(std::move(polyline));
last_end_point_valid = true;
last_end_point = multi_path->paths.back().polyline.last_point();
last_end_point = multi_path->paths.back().polyline.last_point().to_point();
}
}
if (!multi_path->empty())
@@ -582,7 +634,9 @@ inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons
for (Polygon &poly : loops) {
if (poly.is_valid()) {
ExtrusionPath path(role, mm3_per_mm, width, height);
path.polyline.points = std::move(poly.points);
path.polyline.points.reserve(poly.points.size() + 1);
for (const Point &pt : poly.points)
path.polyline.points.emplace_back(Point3(pt, 0));
path.polyline.points.push_back(path.polyline.points.front());
dst.emplace_back(new ExtrusionLoop(std::move(path)));
}
@@ -597,11 +651,11 @@ inline void extrusion_entities_append_loops_and_paths(ExtrusionEntitiesPtr &dst,
if (polyline.is_valid()) {
if (polyline.is_closed()) {
ExtrusionPath extrusion_path(role, mm3_per_mm, width, height);
extrusion_path.polyline = std::move(polyline);
extrusion_path.polyline = Polyline3(std::move(polyline));
dst.emplace_back(new ExtrusionLoop(std::move(extrusion_path)));
} else {
ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height);
extrusion_path->polyline = std::move(polyline);
extrusion_path->polyline = Polyline3(std::move(polyline));
dst.emplace_back(extrusion_path);
}
}

View File

@@ -118,8 +118,8 @@ public:
ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = erMixed) const
{ return this->no_sort ? *this : chained_path_from(this->entities, start_near, role); }
void reverse() override;
const Point& first_point() const override { return this->entities.front()->first_point(); }
const Point& last_point() const override { return this->entities.back()->last_point(); }
Point first_point() const override { return this->entities.front()->first_point(); }
Point last_point() const override { return this->entities.back()->last_point(); }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;

View File

@@ -962,7 +962,7 @@ void ExtrusionSimulator::extrude_to_accumulator(const ExtrusionPath &path, const
w = scale_(path.mm3_per_mm / path.height) * scalex;
// printf("scalex: %f, scaley: %f\n", scalex, scaley);
// printf("bbox: %d,%d %d,%d\n", bbox.min.x(), bbox.min.y, bbox.max.x(), bbox.max.y);
for (Points::const_iterator it = path.polyline.points.begin(); it != path.polyline.points.end(); ++ it) {
for (Points3::const_iterator it = path.polyline.points.begin(); it != path.polyline.points.end(); ++ it) {
// printf("point %d,%d\n", it->x+shift.x(), it->y+shift.y);
ExtrusionPoint ept;
ept.center = V2f(float((*it)(0)+shift.x()-bbox.min.x()) * scalex, float((*it)(1)+shift.y()-bbox.min.y()) * scaley);

View File

@@ -1218,6 +1218,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
f->set_bounding_box(bbox);
f->layer_id = this->id();
{
const auto &rcfg = m_regions[surface_fill.region_id]->region().config();
f->dont_alternate_fill_direction = rcfg.zaa_enabled && rcfg.zaa_dont_alternate_fill_direction;
}
f->z = this->print_z;
f->angle = surface_fill.params.angle;
f->fixed_angle = surface_fill.params.fixed_angle;
@@ -1418,6 +1422,10 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
f->set_bounding_box(bbox);
f->layer_id = this->id() - this->object()->get_layer(0)->id(); // We need to subtract raft layers.
{
const auto &rcfg = m_regions[surface_fill.region_id]->region().config();
f->dont_alternate_fill_direction = rcfg.zaa_enabled && rcfg.zaa_dont_alternate_fill_direction;
}
f->z = this->print_z;
f->angle = surface_fill.params.angle;
f->fixed_angle = surface_fill.params.fixed_angle;
@@ -1595,6 +1603,7 @@ void Layer::make_ironing()
for (size_t i = 0; i < by_extruder.size();) {
// Find span of regions equivalent to the ironing operation.
IroningParams &ironing_params = by_extruder[i];
f->dont_alternate_fill_direction = ironing_params.layerm->region().config().zaa_enabled && ironing_params.layerm->region().config().zaa_dont_alternate_fill_direction;
// Create the filler object.
if( f_pattern != ironing_params.pattern )
{

View File

@@ -308,7 +308,9 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
} else if (this->layer_id != size_t(-1) && !fixed_angle) {
// alternate fill direction
//Orca: Do not alternate direction if Fill.fixed_angle is true
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
if (!this->dont_alternate_fill_direction) {
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
}
} else {
// printf("Layer_ID undefined!\n");
}

View File

@@ -141,6 +141,7 @@ public:
// BBS: all no overlap expolygons in same layer
ExPolygons no_overlap_expolygons;
bool dont_alternate_fill_direction = false;
static float infill_anchor;
static float infill_anchor_max;

View File

@@ -3088,12 +3088,13 @@ bool FillRectilinear::fill_surface_trapezoidal(
case 0: // Grid / Trapezoidal
{
// Generate a non-crossing trapezoidal pattern to avoid overextrusion at intersections when `multiline > 1`.
// P1--P2
// / \
// P0/ \P3__P4
// P2--P3
// / \
// P0_P1/ \P4_
//
// P1x-P2x=P3x-P4x=d1
// P0y-P1y=P2y-P3y=d2
// P0xP1x=P4xP0x=d1/2
// P2xP3x=d1
// P1yP2y=P2yP3y=d2
const coord_t d2 = coord_t(0.5 * period - d1);
@@ -3113,11 +3114,11 @@ bool FillRectilinear::fill_surface_trapezoidal(
// Build complete rows from xmin to xmax
for (coord_t x = xmin; x < xmax; x += period) {
// Normal row
base_row_normal.points.emplace_back(Point(x, d1 / 2)); // P0
base_row_normal.points.emplace_back(Point(x + d1, d1 / 2)); // P1
base_row_normal.points.emplace_back(Point(x + d1 + d2, d1 / 2 + d2)); // P2
base_row_normal.points.emplace_back(Point(x + 2 * d1 + d2, d1 / 2 + d2)); // P3
base_row_normal.points.emplace_back(Point(x + 2 * d1 + 2 * d2, d1 / 2)); // P4
base_row_normal.points.emplace_back(Point(x, d1 / 2)); // P0
base_row_normal.points.emplace_back(Point(x + d1 / 2, d1 / 2)); // P1
base_row_normal.points.emplace_back(Point(x + d1 / 2 + d2, d1 / 2 + d2)); // P2
base_row_normal.points.emplace_back(Point(x + d1 / 2 + d2 + d1, d1 / 2 + d2)); // P3
base_row_normal.points.emplace_back(Point(x + period - d1 / 2, d1 / 2)); // P4
}
// Flipped row (mirrored vertically)
@@ -3150,8 +3151,6 @@ bool FillRectilinear::fill_surface_trapezoidal(
for (Polyline& pl : polylines) {
for (Point& p : pl.points) {
std::swap(p.x(), p.y());
p.x() += d1 / 2;
p.y() -= d1 / 2;
}
}
}
@@ -3165,8 +3164,8 @@ bool FillRectilinear::fill_surface_trapezoidal(
// / \
// P0/ \P3_P4
// ----------------
// P1x-P2x=P3x-P4x=d2
// P0y-P1y=P2y-P3y=h-2d1
// P1xP2x=P3xP4x=d2
// P0yP1y=P2yP3y=h-2d1
//
// Triangular pattern density adjustment:

View File

@@ -1,5 +1,6 @@
#include "BoundingBox.hpp"
#include "Config.hpp"
#include "GCodeWriter.hpp"
#include "Polygon.hpp"
#include "PrintConfig.hpp"
#include "libslic3r.h"
@@ -22,10 +23,12 @@
#include "Time.hpp"
#include "GCode/ExtrusionProcessor.hpp"
#include <algorithm>
#include <cfloat>
#include <cmath>
#include <cstdlib>
#include <chrono>
#include <iostream>
#include <iterator>
#include <math.h>
#include <stdlib.h>
#include <string>
@@ -2416,6 +2419,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_max_layer_z = 0.f;
m_last_width = 0.f;
m_is_role_based_fan_on.fill(false);
m_role_based_fan_marker_layer.fill(-1);
m_fan_mover.release();
@@ -5521,12 +5525,12 @@ void GCode::set_extruders(const std::vector<unsigned int> &extruder_ids)
void GCode::set_origin(const Vec2d &pointf)
{
// if origin increases (goes towards right), last_pos decreases because it goes towards left
const Point translate(
const Point3 translate(
scale_(m_origin(0) - pointf(0)),
scale_(m_origin(1) - pointf(1))
);
m_last_pos += translate;
m_wipe.path.translate(translate);
m_wipe.path.translate(translate.to_point());
m_origin = pointf;
}
@@ -5603,11 +5607,15 @@ static std::unique_ptr<EdgeGrid::Grid> calculate_layer_edge_grid(const Layer& la
return out;
}
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed, const ExtrusionEntitiesPtr& region_perimeters, const Point* start_point)
std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref,
const std::string& description,
double speed,
const ExtrusionEntitiesPtr& region_perimeters,
const Point* start_point)
{
// get a copy; don't modify the orientation of the original loop object otherwise
// next copies (if any) would not detect the correct orientation
ExtrusionLoop loop = loop_ref;
bool is_hole = (loop.loop_role() & elrHole) == elrHole;
@@ -5682,13 +5690,14 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
const double nozzle_diam = nozzle_diameter;
// note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding"
Point previous_point = paths.front().polyline.points[1];
Point current_point = paths.front().polyline.points.front();
Point next_point = paths.back().polyline.points.back();
Point previous_point = Point(paths.front().polyline.points[1].x(), paths.front().polyline.points[1].y());
Point current_point = Point(paths.front().polyline.points.front().x(), paths.front().polyline.points.front().y());
Point next_point = Point(paths.back().polyline.points.back().x(), paths.back().polyline.points.back().y());
// can happen if seam_gap is null
if (next_point == current_point) {
next_point = paths.back().polyline.points[paths.back().polyline.points.size() - 2];
const Point3 &p3 = paths.back().polyline.points[paths.back().polyline.points.size() - 2];
next_point = Point(p3.x(), p3.y());
}
Point a = next_point; // second point
@@ -5735,7 +5744,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// inside the model
if(discoveredTouchingLines > 1){
// use extrude instead of travel_to_xy to trigger the unretract
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
ExtrusionPath fake_path_wipe(Polyline3(Points3{Point3(pt), Point3(current_point)}), paths.front());
fake_path_wipe.set_force_no_extrusion(true);
fake_path_wipe.mm3_per_mm = 0;
//fake_path_wipe.set_extrusion_role(erExternalPerimeter);
@@ -5771,7 +5780,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
if (!enable_seam_slope) {
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
gcode += this->_extrude(*path, description, speed_for_path(*path));
// Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed
// Orca: Adaptive PA - dont adapt PA after the first multipath extrusion is completed
// as we have already set the PA value to the average flow over the totality of the path
// in the first extrude move
// TODO: testing is needed with slope seams and adaptive PA.
@@ -5829,10 +5838,12 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
for (ExtrusionPath &path : paths) {
//BBS: Don't need to save duplicated point into wipe path
if (!m_wipe.path.empty() && !path.empty() &&
m_wipe.path.last_point() == path.first_point())
m_wipe.path.append(path.polyline.points.begin() + 1, path.polyline.points.end());
else
m_wipe.path.append(path.polyline); // TODO: don't limit wipe to last path
m_wipe.path.last_point() == Point(path.first_point().x(), path.first_point().y())) {
// Convert Points3 to Points
for (auto it = path.polyline.points.begin() + 1; it != path.polyline.points.end(); ++it)
m_wipe.path.append(Point(it->x(), it->y()));
} else
m_wipe.path.append(path.polyline.to_polyline()); // TODO: don't limit wipe to last path
}
}
@@ -5842,8 +5853,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// the side depends on the original winding order of the polygon (inwards for contours, outwards for holes)
//FIXME improve the algorithm in case the loop is tiny.
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
Point a = paths.front().polyline.points[1]; // second point
Point b = *(paths.back().polyline.points.end()-3); // second to last point
const Point3 &a3 = paths.front().polyline.points[1]; // second point
Point a = Point(a3.x(), a3.y());
const Point3 &b3 = *(paths.back().polyline.points.end()-3); // second to last point
Point b = Point(b3.x(), b3.y());
if (is_hole == loop.is_counter_clockwise()) {
// swap points
Point c = a; a = b; b = c;
@@ -5857,8 +5870,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// create the destination point along the first segment and rotate it
// we make sure we don't exceed the segment length because we don't know
// the rotation of the second segment so we might cross the object boundary
Vec2d p1 = paths.front().polyline.points.front().cast<double>();
Vec2d p2 = paths.front().polyline.points[1].cast<double>();
Vec2d p1 = paths.front().polyline.points.front().cast<double>().head<2>();
Vec2d p2 = paths.front().polyline.points[1].cast<double>().head<2>();
Vec2d v = p2 - p1;
double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
double l2 = v.squaredNorm();
@@ -5870,19 +5883,20 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
if (nd * nd < l2)
pt = (p1 + threshold * v * (nd / sqrt(l2))).cast<coord_t>();
//Point pt = ((nd * nd >= l2) ? (p1+v*0.4): (p1 + 0.2 * v * (nd / sqrt(l2)))).cast<coord_t>();
pt.rotate(angle, paths.front().polyline.points.front());
const Point3 &center3 = paths.front().polyline.points.front();
pt.rotate(angle, Point(center3.x(), center3.y()));
// generate the travel move
gcode += m_writer.extrude_to_xy(this->point_to_gcode(pt), 0,"move inwards before travel",true);
gcode += m_writer.extrude_to_xy(this->point_to_gcode(pt), 0, "move inwards before travel", true);
}
return gcode;
}
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed)
std::string GCode::extrude_multi_path(const ExtrusionMultiPath& multipath, const std::string& description, double speed)
{
// extrude along the path
std::string gcode;
//Orca: calculate multipath average mm3_per_mm value over the length of the path.
//This is used for adaptive PA
m_multi_flow_segment_path_pa_set = false; // always emit PA on the first path of the multi-path
@@ -5899,8 +5913,8 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
if (total_multipath_length > 0.0)
m_multi_flow_segment_path_average_mm3_per_mm = weighted_sum_mm3_per_mm / total_multipath_length;
// Orca: end of multipath average mm3_per_mm value calculation
for (ExtrusionPath path : multipath.paths){
for (const ExtrusionPath &path : multipath.paths){
gcode += this->_extrude(path, description, speed);
// Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed
// as we have already set the PA value to the average flow over the totality of the path
@@ -5911,13 +5925,15 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
// BBS
if (m_wipe.enable && FILAMENT_CONFIG(wipe)) {
m_wipe.path = Polyline();
for (ExtrusionPath &path : multipath.paths) {
for (const ExtrusionPath &path : multipath.paths) {
//BBS: Don't need to save duplicated point into wipe path
if (!m_wipe.path.empty() && !path.empty() &&
m_wipe.path.last_point() == path.first_point())
m_wipe.path.append(path.polyline.points.begin() + 1, path.polyline.points.end());
else
m_wipe.path.append(path.polyline); // TODO: don't limit wipe to last path
m_wipe.path.last_point() == Point(path.first_point().x(), path.first_point().y())) {
// Convert Points3 to Points
for (auto it = path.polyline.points.begin() + 1; it != path.polyline.points.end(); ++it)
m_wipe.path.append(Point(it->x(), it->y()));
} else
m_wipe.path.append(path.polyline.to_polyline()); // TODO: don't limit wipe to last path
}
m_wipe.path.reverse();
}
@@ -5925,7 +5941,10 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
return gcode;
}
std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string description, double speed, const ExtrusionEntitiesPtr& region_perimeters)
std::string GCode::extrude_entity(const ExtrusionEntity& entity,
const std::string& description,
double speed,
const ExtrusionEntitiesPtr& region_perimeters)
{
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity))
return this->extrude_path(*path, description, speed);
@@ -5938,7 +5957,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
return "";
}
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed)
std::string GCode::extrude_path(const ExtrusionPath& path, const std::string& description, double speed)
{
// Orca: Reset average multipath flow as this is a single line, single extrude volumetric speed path
m_multi_flow_segment_path_pa_set = false;
@@ -5946,17 +5965,17 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
// description += ExtrusionEntity::role_to_string(path.role());
std::string gcode = this->_extrude(path, description, speed);
if (m_wipe.enable && FILAMENT_CONFIG(wipe)) {
m_wipe.path = path.polyline;
m_wipe.path = path.polyline.to_polyline();
if (is_tree(this->config().support_type) && (path.role() == erSupportMaterial || path.role() == erSupportMaterialInterface || path.role() == erSupportTransition)) {
if ((m_wipe.path.first_point() - m_wipe.path.last_point()).cast<double>().norm() > scale_(0.2)) {
double min_dist = scale_(0.2);
int i = 0;
for (; i < path.polyline.points.size(); i++) {
double dist = (path.polyline.points[i] - path.last_point()).cast<double>().norm();
double dist = (path.polyline.points[i] - path.last_point3()).cast<double>().norm();
if (dist < min_dist) min_dist = dist;
if (min_dist < scale_(0.2) && dist > min_dist) break;
}
m_wipe.path = Polyline(Points(path.polyline.points.begin() + i - 1, path.polyline.points.end()));
m_wipe.path = Polyline3(Points3(path.polyline.points.begin() + i - 1, path.polyline.points.end())).to_polyline();
}
} else
m_wipe.path.reverse();
@@ -5999,11 +6018,11 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
extrusions.emplace_back(ee);
if (! extrusions.empty()) {
m_config.apply(print.get_print_region(&region - &by_region.front()).config());
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point());
for (const ExtrusionEntity *fill : extrusions) {
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
if (eec) {
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos.to_point()).entities)
gcode += this->extrude_entity(*ee, extrusion_name);
} else
gcode += this->extrude_entity(*fill, extrusion_name);
@@ -6034,7 +6053,7 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
if (extrusions.empty())
return gcode;
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point());
const double support_speed = m_config.support_speed.value;
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
@@ -6200,14 +6219,19 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
// Move to first point of extrusion path
// path is 2D. But in slope lift case, lift z is done in travel_to function.
// Add m_need_change_layer_lift_z when change_layer in case of no lift if m_last_pos is equal to path.first_point() by chance
if (!m_last_pos_defined || m_last_pos != path.first_point() || m_need_change_layer_lift_z || slope_need_z_travel) {
Point first_point = path.first_point();
if (!m_last_pos_defined || m_last_pos.to_point() != first_point || m_need_change_layer_lift_z || slope_need_z_travel) {
const bool _last_pos_undefined = !m_last_pos_defined;
gcode += this->travel_to(
path.first_point(),
path.role(),
"move to first " + description + " point",
sloped == nullptr ? DBL_MAX : get_sloped_z(sloped->slope_begin.z_ratio)
);
double z = DBL_MAX;
if (sloped != nullptr) {
z = get_sloped_z(sloped->slope_begin.z_ratio);
} else if (path.z_contoured && !path.polyline.lines().empty()) {
z = unscale_(path.polyline.lines().begin()->a.z()) + m_nominal_z;
}
gcode += this->travel_to(first_point, path.role(), "move to first " + description + " point", z);
// Orca: ensure Z matches planned layer height
if (!slope_need_z_travel && (_last_pos_undefined || m_need_change_layer_lift_z)) {
const std::string z_sync_comment = _last_pos_undefined ?
@@ -6217,6 +6241,19 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
m_need_change_layer_lift_z = false;
}
if (path.z_contoured && !path.polyline.lines().empty()) {
double current_z = m_writer.get_position().z();
double first_z = unscale_(path.polyline.lines().begin()->a.z()) + m_nominal_z;
if (GCodeFormatter::quantize_xyzf(first_z) != GCodeFormatter::quantize_xyzf(current_z)) {
gcode += m_writer.travel_to_z(first_z, "set Z for contouring", true);
}
}
if (!path.z_contoured && sloped == nullptr) {
double current_z = m_writer.get_position().z();
if (GCodeFormatter::quantize_xyzf(current_z) != GCodeFormatter::quantize_xyzf(m_nominal_z)) {
gcode += this->writer().travel_to_z(m_nominal_z, "reset Z after contouring", true);
}
}
// if needed, write the gcode_label_objects_end then gcode_label_objects_start
// should be already done by travel_to, but just in case
@@ -6709,11 +6746,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
assert(m_enable_cooling_markers);
if (fan_on) {
if (!m_is_role_based_fan_on[role]) {
// Orca: CoolingBuffer consumes role fan markers per layer, so continuing
// role-based fan regions need a fresh START marker on each new layer.
if (!m_is_role_based_fan_on[role] || m_role_based_fan_marker_layer[role] != m_layer_index) {
gcode += ";";
gcode += marker_prefix;
gcode += "_FAN_START\n";
m_is_role_based_fan_on[role] = true;
m_role_based_fan_marker_layer[role] = m_layer_index;
}
} else {
if (m_is_role_based_fan_on[role]) {
@@ -6721,6 +6761,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
gcode += marker_prefix;
gcode += "_FAN_END\n";
m_is_role_based_fan_on[role] = false;
m_role_based_fan_marker_layer[role] = -1;
}
}
};
@@ -6803,10 +6844,12 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
}
// BBS: use G1 if not enable arc fitting or has no arc fitting result or in spiral_mode mode or we are doing sloped extrusion
// Attention: G2 and G3 is not supported in spiral_mode mode
if (!m_config.enable_arc_fitting || path.polyline.fitting_result.empty() || m_config.spiral_mode || sloped != nullptr) {
if (!m_config.enable_arc_fitting || path.polyline.fitting_result.empty() || m_config.spiral_mode || sloped != nullptr || path.z_contoured) {
double path_length = 0.;
double total_length = sloped == nullptr ? 0. : path.polyline.length() * SCALING_FACTOR;
for (const Line& line : path.polyline.lines()) {
double saved_z = m_writer.get_position().z();
for (const Line3& line : path.polyline.lines()) {
std::string tempDescription = description;
const double line_length = line.length() * SCALING_FACTOR;
if (line_length < EPSILON)
@@ -6821,16 +6864,35 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
}
}
if (sloped == nullptr) {
if (path.z_contoured) {
// ZAA: Z anti-aliased extrusion with variable Z per point
Vec2d dest2d = this->point_to_gcode(line.b.to_point());
coordf_t z_diff = unscale_(line.b.z());
double extrusion_ratio = 1;
if (path.role() != erIroning) {
extrusion_ratio = (path.height + z_diff) / path.height;
}
double e = dE * extrusion_ratio;
double z = m_nominal_z + z_diff;
if (z < 0.1) {
throw RuntimeError("GCode: very low z");
}
gcode += m_writer.extrude_to_xyz(Vec3d(dest2d.x(), dest2d.y(), z), e,
GCodeWriter::full_gcode_comment ? tempDescription : "");
} else if (sloped == nullptr) {
// Normal extrusion
gcode += m_writer.extrude_to_xy(
this->point_to_gcode(line.b),
this->point_to_gcode(line.b.to_point()),
dE,
GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion());
} else {
// Sloped extrusion
const auto [z_ratio, e_ratio] = sloped->interpolate(path_length / total_length);
Vec2d dest2d = this->point_to_gcode(line.b);
Vec2d dest2d = this->point_to_gcode(line.b.to_point());
Vec3d dest3d(dest2d(0), dest2d(1), get_sloped_z(z_ratio));
gcode += m_writer.extrude_to_xyz(
dest3d,
@@ -6849,7 +6911,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
size_t end_index = fitting_result[fitting_index].end_point_index;
for (size_t point_index = start_index + 1; point_index < end_index + 1; point_index++) {
tempDescription = description;
const Line line = Line(path.polyline.points[point_index - 1], path.polyline.points[point_index]);
const Line line = Line(path.polyline.points[point_index - 1].to_point(), path.polyline.points[point_index].to_point());
const double line_length = line.length() * SCALING_FACTOR;
if (line_length < EPSILON)
continue;
@@ -6907,14 +6969,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
double total_length = 0;
if (sloped != nullptr) {
// Calculate total extrusion length
Points p;
Points3 p;
p.reserve(new_points.size());
std::transform(new_points.begin(), new_points.end(), std::back_inserter(p), [](const ProcessedPoint& pp) { return pp.p; });
Polyline l(p);
Polyline3 l(p);
total_length = l.length() * SCALING_FACTOR;
}
gcode += m_writer.set_speed(last_set_speed, "", comment);
Vec2d prev = this->point_to_gcode_quantized(new_points[0].p);
Vec3d prev = this->point_to_gcode_quantized(new_points[0].p);
bool pre_fan_enabled = false;
bool cur_fan_enabled = false;
if( m_enable_cooling_markers && enable_overhang_bridge_fan)
@@ -6928,7 +6990,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
std::string tempDescription = description;
const ProcessedPoint &processed_point = new_points[i];
const ProcessedPoint &pre_processed_point = new_points[i-1];
Vec2d p = this->point_to_gcode_quantized(processed_point.p);
Vec3d p = this->point_to_gcode_quantized(processed_point.p);
if (m_enable_cooling_markers) {
if (enable_overhang_bridge_fan) {
cur_fan_enabled = check_overhang_fan(processed_point.overlap, path.role());
@@ -7010,9 +7072,26 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
}
}
if (sloped == nullptr) {
if (path.z_contoured) {
Vec2d dest2d = p.head<2>();
coordf_t z_diff = unscale_(processed_point.p.z());
double extrusion_ratio = 1;
if (path.role() != erIroning) {
extrusion_ratio = (path.height + z_diff) / path.height;
}
double e = dE * extrusion_ratio;
double z = m_nominal_z + z_diff;
if (z < 0.1) {
throw RuntimeError("GCode: very low z");
}
gcode += m_writer.extrude_to_xyz(Vec3d(dest2d.x(), dest2d.y(), z), e,
GCodeWriter::full_gcode_comment ? tempDescription : "");
} else if (sloped == nullptr) {
// Normal extrusion
gcode += m_writer.extrude_to_xy(p, dE, GCodeWriter::full_gcode_comment ? tempDescription : "");
gcode += m_writer.extrude_to_xy(p.head<2>(), dE, GCodeWriter::full_gcode_comment ? tempDescription : "");
} else {
// Sloped extrusion
const auto [z_ratio, e_ratio] = sloped->interpolate(path_length / total_length);
@@ -7893,6 +7972,13 @@ Vec2d GCode::point_to_gcode(const Point &point) const
return unscale(point) + m_origin - extruder_offset;
}
Vec3d GCode::point_to_gcode(const Point3& point) const
{
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
Vec2d xy = unscale(point.to_point()) + m_origin - extruder_offset;
return Vec3d(xy.x(), xy.y(), unscale_(point.z()));
}
// convert a model-space scaled point into G-code coordinates
Point GCode::gcode_to_point(const Vec2d &point) const
{
@@ -7910,6 +7996,11 @@ Vec2d GCode::point_to_gcode_quantized(const Point& point) const
return { GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()) };
}
Vec3d GCode::point_to_gcode_quantized(const Point3& point) const
{
Vec3d p = this->point_to_gcode(point);
return {GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()), GCodeFormatter::quantize_xyzf(p.z())};
}
// Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed
// during infill/perimeter wiping, or normally (depends on wiping_entities parameter)

View File

@@ -221,10 +221,12 @@ public:
const Vec2d& origin() const { return m_origin; }
void set_origin(const Vec2d &pointf);
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
const Point& last_pos() const { return m_last_pos; }
Point last_pos() const { return m_last_pos.to_point(); }
Vec2d point_to_gcode(const Point &point) const;
Vec3d point_to_gcode(const Point3& point) const;
Point gcode_to_point(const Vec2d &point) const;
Vec2d point_to_gcode_quantized(const Point& point) const;
Vec3d point_to_gcode_quantized(const Point3& point) const;
const FullPrintConfig &config() const { return m_config; }
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
@@ -383,7 +385,8 @@ private:
void check_placeholder_parser_failed();
size_t get_extruder_id(unsigned int filament_id) const;
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
void set_last_pos(const Point &pos) { m_last_pos = Point3(pos, 0); m_last_pos_defined = true; }
void set_last_pos(const Point3 &pos) { m_last_pos = pos; m_last_pos_defined = true; }
bool last_pos_defined() const { return m_last_pos_defined; }
void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::string preamble();
@@ -391,13 +394,20 @@ private:
std::string change_layer(coordf_t print_z);
// Orca: pass the complete collection of region perimeters to the extrude loop to check whether the wipe before external loop
// should be executed
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1., const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr());
std::string extrude_entity(const ExtrusionEntity& entity,
const std::string& description = "",
double speed = -1.,
const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr());
// Orca: pass the complete collection of region perimeters to the extrude loop to check whether the wipe before external loop
// should be executed
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr(), const Point* start_point = nullptr);
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
std::string extrude_loop(const ExtrusionLoop& loop,
const std::string& description,
double speed = -1.,
const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr(),
const Point* start_point = nullptr);
std::string extrude_multi_path(const ExtrusionMultiPath& multipath, const std::string& description = "", double speed = -1.);
std::string extrude_path(const ExtrusionPath& path, const std::string& description = "", double speed = -1.);
// Orca: Adaptive PA variables
// Used for adaptive PA when extruding paths with multiple, varying flow segments.
// This contains the sum of the mm3_per_mm values weighted by the length of each path segment.
@@ -549,6 +559,7 @@ private:
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
// ORCA: Add support for role based fan speed control
std::array<bool, ExtrusionRole::erCount> m_is_role_based_fan_on;
std::array<int, ExtrusionRole::erCount> m_role_based_fan_marker_layer;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.
bool m_enable_extrusion_role_markers;
@@ -584,7 +595,7 @@ private:
std::map<std::string, std::vector<std::string>> m_placeholder_error_messages;
#endif
Point m_last_pos;
Point3 m_last_pos;
bool m_last_pos_defined;
std::unique_ptr<CoolingBuffer> m_cooling_buffer;

View File

@@ -87,7 +87,7 @@ public:
for (int i = b; i < e; ++i) {
for (const ExtrusionPath &path : _piles[i].paths) {
if (path.is_force_no_extrusion() == false) {
Polyline check_polyline = path.polyline;
Polyline check_polyline = path.polyline.to_polyline();
check_polyline.translate(_offset);
Lines tmpLines = check_polyline.lines();
for (const Line &line : tmpLines) { lines.emplace_back(line, _id, path.role()); }

View File

@@ -27,19 +27,19 @@
namespace Slic3r {
struct ExtendedPoint
template<int Dim> struct ExtendedPoint
{
Vec2d position;
Eigen::Matrix<double, Dim, 1, Eigen::DontAlign> position;
float distance;
float curvature;
};
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename POINTS, typename L>
std::vector<ExtendedPoint> estimate_points_properties(const POINTS &input_points,
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
float flow_width,
float max_line_length = -1.0f,
float min_distance = -1.0f)
std::vector<ExtendedPoint<L::Dim>> estimate_points_properties(const POINTS& input_points,
const AABBTreeLines::LinesDistancer<L>& unscaled_prev_layer,
float flow_width,
float max_line_length = -1.0f,
float min_distance = -1.0f)
{
bool looped = input_points.front() == input_points.back();
std::function<size_t(size_t,size_t)> get_prev_index = [](size_t idx, size_t count) {
@@ -78,35 +78,36 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
double min_spacing = flow_width*0.25;
using AABBScalar = typename AABBTreeLines::LinesDistancer<L>::Scalar;
using Vec = Eigen::Matrix<double, L::Dim, 1, Eigen::DontAlign>;
if (input_points.empty())
return {};
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
auto maybe_unscale = [](const P& p) -> Vec { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
std::vector<ExtendedPoint> points;
std::vector<ExtendedPoint<L::Dim>> points;
points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
{
ExtendedPoint start_point{maybe_unscale(input_points.front())};
auto [distance, nearest_line,
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
ExtendedPoint<L::Dim> start_point{maybe_unscale(input_points.front())};
auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(
start_point.position.template cast<AABBScalar>());
start_point.distance = distance + boundary_offset;
points.push_back(start_point);
}
for (size_t i = 1; i < input_points.size(); i++) {
ExtendedPoint next_point{maybe_unscale(input_points[i])};
ExtendedPoint<L::Dim> next_point{maybe_unscale(input_points[i])};
auto [distance, nearest_line,
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.template cast<AABBScalar>());
next_point.distance = distance + boundary_offset;
// Intersection handling
if (ADD_INTERSECTIONS &&
((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) {
const ExtendedPoint &prev_point = points.back();
auto intersections = unscaled_prev_layer.template intersections_with_line<true>(
L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()});
const ExtendedPoint<L::Dim>& prev_point = points.back();
auto intersections = unscaled_prev_layer.template intersections_with_line<true>(
L{prev_point.position.template cast<AABBScalar>(), next_point.position.template cast<AABBScalar>()});
for (const auto &intersection : intersections) {
ExtendedPoint p{};
ExtendedPoint<L::Dim> p{};
p.position = intersection.first.template cast<double>();
p.distance = boundary_offset;
// ORCA: Filter out points that are introduced at intersections if their distance from the previous or next point is not meaningful
@@ -121,12 +122,12 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
// Segmentation handling
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
std::vector<ExtendedPoint> new_points;
std::vector<ExtendedPoint<L::Dim>> new_points;
new_points.reserve(points.size() * 2);
new_points.push_back(points.front());
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
const ExtendedPoint &curr = points[point_idx];
const ExtendedPoint &next = points[point_idx + 1];
const ExtendedPoint<L::Dim>& curr = points[point_idx];
const ExtendedPoint<L::Dim>& next = points[point_idx + 1];
if ((curr.distance > -boundary_offset && curr.distance < boundary_offset + 2.0f) ||
(next.distance > -boundary_offset && next.distance < boundary_offset + 2.0f)) {
@@ -144,10 +145,10 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
double t1 = std::max(a0, a1);
if (t0 < 1.0) {
Vec2d p0 = curr.position + t0 * (next.position - curr.position);
auto [p0_dist, p0_near_l,
p0_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p0.cast<AABBScalar>());
ExtendedPoint new_p{};
Vec p0 = curr.position + t0 * (next.position - curr.position);
auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(
p0.template cast<AABBScalar>());
ExtendedPoint<L::Dim> new_p{};
new_p.position = p0;
new_p.distance = float(p0_dist + boundary_offset);
// ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change
@@ -161,10 +162,10 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
}
}
if (t1 > 0.0) {
Vec2d p1 = curr.position + t1 * (next.position - curr.position);
auto [p1_dist, p1_near_l,
p1_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p1.cast<AABBScalar>());
ExtendedPoint new_p{};
Vec p1 = curr.position + t1 * (next.position - curr.position);
auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(
p1.template cast<AABBScalar>());
ExtendedPoint<L::Dim> new_p{};
new_p.position = p1;
new_p.distance = float(p1_dist + boundary_offset);
// ORCA: only create a new point in the path if the new point overhang distance will be used to generate a speed change
@@ -186,21 +187,21 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
// Maximum line length handling
if (max_line_length > 0) {
std::vector<ExtendedPoint> new_points;
std::vector<ExtendedPoint<L::Dim>> new_points;
new_points.reserve(points.size() * 2);
{
for (size_t i = 0; i + 1 < points.size(); i++) {
const ExtendedPoint &curr = points[i];
const ExtendedPoint &next = points[i + 1];
const ExtendedPoint<L::Dim>& curr = points[i];
const ExtendedPoint<L::Dim>& next = points[i + 1];
new_points.push_back(curr);
double len = (next.position - curr.position).squaredNorm();
double t = sqrt((max_line_length * max_line_length) / len);
size_t new_point_count = 1.0 / t;
for (size_t j = 1; j < new_point_count + 1; j++) {
Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t);
Vec pos = curr.position * (1.0 - j * t) + next.position * (j * t);
auto [p_dist, p_near_l,
p_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(pos.cast<AABBScalar>());
ExtendedPoint new_p{};
p_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(pos.template cast<AABBScalar>());
ExtendedPoint<L::Dim> new_p{};
new_p.position = pos;
new_p.distance = float(p_dist + boundary_offset);
@@ -219,8 +220,8 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
float accumulated_distance = 0;
std::vector<float> distances_for_curvature(points.size());
for (size_t point_idx = 0; point_idx < points.size(); ++point_idx) {
const ExtendedPoint &a = points[point_idx];
const ExtendedPoint &b = points[get_prev_index(point_idx, points.size())];
const ExtendedPoint<L::Dim>& a = points[point_idx];
const ExtendedPoint<L::Dim>& b = points[get_prev_index(point_idx, points.size())];
distances_for_curvature[point_idx] = (b.position - a.position).norm();
accumulated_distance += distances_for_curvature[point_idx];
@@ -229,9 +230,9 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
if (accumulated_distance > EPSILON)
for (float window_size : {3.0f, 9.0f, 16.0f}) {
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
ExtendedPoint &current = points[point_idx];
ExtendedPoint<L::Dim>& current = points[point_idx];
Vec2d back_position = current.position;
Vec back_position = current.position;
{
size_t back_point_index = point_idx;
float dist_backwards = 0;
@@ -251,7 +252,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
}
}
Vec2d front_position = current.position;
Vec front_position = current.position;
{
size_t front_point_index = point_idx;
float dist_forwards = 0;
@@ -271,7 +272,9 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
}
}
float new_curvature = angle(current.position - back_position, front_position - current.position) / window_size;
float new_curvature = angle((current.position - back_position).template head<2>(),
(front_position - current.position).template head<2>()) /
window_size;
if (abs(current.curvature) < abs(new_curvature)) {
current.curvature = new_curvature;
}
@@ -283,15 +286,15 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
struct ProcessedPoint
{
Point p;
Point3 p;
float speed = 1.0f;
float overlap = 1.0f;
};
class ExtrusionQualityEstimator
{
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
std::unordered_map<const PrintObject*, AABBTreeLines::LinesDistancer<Linef3>> prev_layer_boundaries;
std::unordered_map<const PrintObject*, AABBTreeLines::LinesDistancer<Linef3>> next_layer_boundaries;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> prev_curled_extrusions;
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> next_curled_extrusions;
const PrintObject *current_object;
@@ -304,7 +307,7 @@ public:
if (layer == nullptr) return;
const PrintObject *object = obj;
prev_layer_boundaries[object] = next_layer_boundaries[object];
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef3>{to_unscaled_linesf3(layer->lslices)};
prev_curled_extrusions[object] = next_curled_extrusions[object];
next_curled_extrusions[object] = AABBTreeLines::LinesDistancer<CurledLine>{layer->curled_lines};
}
@@ -359,56 +362,54 @@ public:
smallest_distance_with_lower_speed=-1.f;
// Orca: Pass to the point properties estimator the smallest ovehang distance that triggers a slowdown (smallest_distance_with_lower_speed)
std::vector<ExtendedPoint> extended_points = estimate_points_properties<true, true, true, true>
(path.polyline.points,
prev_layer_boundaries[current_object],
path.width,
-1,
smallest_distance_with_lower_speed);
std::vector<ExtendedPoint<3>> extended_points =
estimate_points_properties<true, true, true, true>(path.polyline.points, prev_layer_boundaries[current_object], path.width, -1,
smallest_distance_with_lower_speed);
const auto width_inv = 1.0f / path.width;
std::vector<ProcessedPoint> processed_points;
processed_points.reserve(extended_points.size());
for (size_t i = 0; i < extended_points.size(); i++) {
const ExtendedPoint &curr = extended_points[i];
const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
const ExtendedPoint<3>& curr = extended_points[i];
const ExtendedPoint<3>& next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
float artificial_distance_to_curled_lines = 0.0;
if(slowdown_for_curled_edges) {
// The following code artifically increases the distance to provide slowdown for extrusions that are over curled lines
const double dist_limit = 10.0 * path.width;
{
Vec2d middle = 0.5 * (curr.position + next.position);
auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle), scale_(dist_limit));
if (!line_indices.empty()) {
double len = (next.position - curr.position).norm();
// For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line
Vec3d middle = 0.5 * (curr.position + next.position);
auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle),
scale_(dist_limit));
if (!line_indices.empty()) {
double len = (next.position - curr.position).norm();
// For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line
// The whole segment gets slower unnecesarily. For these long lines, we do additional check whether it is worth slowing down.
// NOTE that this is still quite rough approximation, e.g. we are still checking lines only near the middle point
// TODO maybe split the lines into smaller segments before running this alg? but can be demanding, and GCode will be huge
if (len > 2) {
Vec2d dir = Vec2d(next.position - curr.position) / len;
Vec2d right = Vec2d(-dir.y(), dir.x());
Vec2d dir = Vec2d(next.position.head<2>() - curr.position.head<2>()) / len;
Vec2d right = Vec2d(-dir.y(), dir.x());
Polygon box_of_influence = {
scaled(Vec2d(curr.position + right * dist_limit)),
scaled(Vec2d(next.position + right * dist_limit)),
scaled(Vec2d(next.position - right * dist_limit)),
scaled(Vec2d(curr.position - right * dist_limit)),
};
Polygon box_of_influence = {
scaled(Vec2d(curr.position.head<2>() + right * dist_limit)),
scaled(Vec2d(next.position.head<2>() + right * dist_limit)),
scaled(Vec2d(next.position.head<2>() - right * dist_limit)),
scaled(Vec2d(curr.position.head<2>() - right * dist_limit)),
};
double projected_lengths_sum = 0;
for (size_t idx : line_indices) {
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence});
double projected_lengths_sum = 0;
for (size_t idx : line_indices) {
const CurledLine& line = prev_curled_extrusions[current_object].get_line(idx);
Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence});
if (inside.empty())
continue;
double projected_length = abs(dir.dot(unscaled(Vec2d((inside.back().b - inside.back().a).cast<double>()))));
projected_lengths_sum += projected_length;
}
if (projected_lengths_sum < 0.4 * len) {
line_indices.clear();
}
}
}
if (projected_lengths_sum < 0.4 * len) {
line_indices.clear();
}
}
for (size_t idx : line_indices) {
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
@@ -418,9 +419,9 @@ public:
(line.curled_height / (path.height * 10.0f)); // max_curled_height_factor from SupportSpotGenerator
artificial_distance_to_curled_lines = std::max(artificial_distance_to_curled_lines, dist);
}
}
}
}
}
}
}
auto calculate_speed = [&speed_sections, &original_speed](float distance) {
float final_speed;
@@ -452,8 +453,8 @@ public:
}
float overlap = std::min(1 - (curr.distance+artificial_distance_to_curled_lines) * width_inv, 1 - (next.distance+artificial_distance_to_curled_lines) * width_inv);
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
processed_points.push_back({Point3(scaled(curr.position)), extrusion_speed, overlap});
}
return processed_points;
}

View File

@@ -30,7 +30,7 @@ static inline BoundingBox extrusion_polyline_extents(const Polyline &polyline, c
static inline BoundingBoxf extrusionentity_extents(const ExtrusionPath &extrusion_path)
{
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width)));
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline.to_polyline(), coord_t(scale_(0.5 * extrusion_path.width)));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);
@@ -44,7 +44,7 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionLoop &extrusio
{
BoundingBox bbox;
for (const ExtrusionPath &extrusion_path : extrusion_loop.paths)
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline.to_polyline(), coord_t(scale_(0.5 * extrusion_path.width))));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);
@@ -58,7 +58,7 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionMultiPath &ext
{
BoundingBox bbox;
for (const ExtrusionPath &extrusion_path : extrusion_multi_path.paths)
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline.to_polyline(), coord_t(scale_(0.5 * extrusion_path.width))));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);

View File

@@ -1514,7 +1514,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop,
current.path_idx = next_idx_modulo(current.path_idx, loop.paths.size());
current.segment_idx = 0;
}
current.foot_pt = loop.paths[current.path_idx].polyline.points[current.segment_idx];
current.foot_pt = loop.paths[current.path_idx].polyline.points[current.segment_idx].to_point();
return current;
};
@@ -1527,7 +1527,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop,
size_t closest_perimeter_point_index = 0;
{ // local space for the closest_perimeter_point_index
Perimeter *closest_perimeter = nullptr;
ExtrusionLoop::ClosestPathPoint closest_point{0,0,loop.paths[0].polyline.points[0]};
ExtrusionLoop::ClosestPathPoint closest_point{0, 0, loop.paths[0].polyline.points[0].to_point()};
size_t points_count = std::accumulate(loop.paths.begin(), loop.paths.end(), 0, [](size_t acc,const ExtrusionPath& p) {
return acc + p.polyline.points.size();
});

View File

@@ -929,6 +929,11 @@ std::string GCodeWriter::extrude_arc_to_xy(const Vec2d& point, const Vec2d& cent
std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment, bool force_no_extrusion)
{
// Check if Z actually changes (at export precision) before emitting it.
// ZAA sloped extrusions call this for every segment, but many consecutive
// segments share the same quantized Z — emitting it every time is redundant.
bool z_changed = (GCodeG1Formatter::quantize_xyzf(point(2)) != GCodeG1Formatter::quantize_xyzf(m_pos(2)));
m_pos = point;
m_lifted = 0;
if (!force_no_extrusion)
@@ -938,7 +943,10 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
Vec3d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset, point(2) };
GCodeG1Formatter w;
w.emit_xyz(point_on_plate);
if (z_changed)
w.emit_xyz(point_on_plate);
else
w.emit_xy(Vec2d(point_on_plate.x(), point_on_plate.y()));
if (!force_no_extrusion)
w.emit_e(filament()->E());
//BBS

View File

@@ -26,6 +26,10 @@ namespace FillLightning {
class Generator;
};
namespace sla {
class IndexedMesh;
};
class LayerRegion
{
public:
@@ -191,6 +195,7 @@ public:
FillAdaptive::Octree *support_fill_octree,
FillLightning::Generator* lightning_generator) const;
void make_ironing();
void make_contour_z(const sla::IndexedMesh &mesh);
void export_region_slices_to_svg(const char *path) const;
void export_region_fill_surfaces_to_svg(const char *path) const;

View File

@@ -3,6 +3,7 @@
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
#include "PerimeterGenerator.hpp"
#include "Point.hpp"
#include "Print.hpp"
#include "Surface.hpp"
#include "BoundingBox.hpp"

View File

@@ -224,17 +224,28 @@ using CurledLines = std::vector<CurledLine>;
class Line3
{
public:
Line3() : a(Vec3crd::Zero()), b(Vec3crd::Zero()) {}
Line3(const Vec3crd& _a, const Vec3crd& _b) : a(_a), b(_b) {}
Line3() : a(Point3()), b(Point3()) {}
Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {}
// Backward compatibility with Vec3crd
Line3(const Vec3crd& _a, const Vec3crd& _b) : a(Point3(_a)), b(Point3(_b)) {}
double length() const { return (this->a - this->b).cast<double>().norm(); }
Vec3crd vector() const { return this->b - this->a; }
Point3 vector() const { Vec3crd v = this->b - this->a; return Point3(v.x(), v.y(), v.z()); }
Point3 midpoint() const { return Point3((this->a.x() + this->b.x()) / 2, (this->a.y() + this->b.y()) / 2, (this->a.z() + this->b.z()) / 2); }
Vec3crd a;
Vec3crd b;
// Convert to 2D line by dropping Z coordinate
Line to_line() const { return Line(this->a.to_point(), this->b.to_point()); }
static inline double distance_to_squared(const Point3& point, const Point3& a, const Point3& b)
{
return line_alg::distance_to_squared(Line3{a, b}, Vec<3, coord_t>{point});
}
Point3 a;
Point3 b;
static const constexpr int Dim = 3;
using Scalar = Vec3crd::Scalar;
using Scalar = coord_t;
};
class Linef
@@ -243,6 +254,10 @@ public:
Linef() : a(Vec2d::Zero()), b(Vec2d::Zero()) {}
Linef(const Vec2d& _a, const Vec2d& _b) : a(_a), b(_b) {}
Vec2d vector() const { return this->b - this->a; }
Vec2d unit_vector() const { return (length() == 0.0) ? Vec2d::Zero() : vector().normalized(); }
double length() const { return vector().norm(); }
Vec2d a;
Vec2d b;
@@ -256,6 +271,7 @@ class Linef3
public:
Linef3() : a(Vec3d::Zero()), b(Vec3d::Zero()) {}
Linef3(const Vec3d& _a, const Vec3d& _b) : a(_a), b(_b) {}
Linef3(const Vec2d& _a, const Vec2d& _b, double z) : a(Vec3d(_a.x(), _a.y(), z)), b(Vec3d(_b.x(), _b.y(), z)) {}
Vec3d intersect_plane(double z) const;
void scale(double factor) { this->a *= factor; this->b *= factor; }
@@ -263,6 +279,32 @@ public:
Vec3d unit_vector() const { return (length() == 0.0) ? Vec3d::Zero() : vector().normalized(); }
double length() const { return vector().norm(); }
double distance_to_infinite_squared(const Vec3d &point, Vec3d *closest_point) const {
const Vec3d v = this->b - this->a;
const Vec3d va = point - this->a;
const double l2 = v.squaredNorm();
if (l2 == 0.) {
// a == b case
*closest_point = this->a;
return va.squaredNorm();
}
// Consider the line extending the segment, parameterized as a + t (b - a).
// Find parameter value t of the projection of point onto the line.
const double t = va.dot(v) / l2;
*closest_point = this->a + t * v;
return (point - *closest_point).squaredNorm();
}
double distance_to_infinite_squared(const Vec3d &point) const {
Vec3d nearest_point;
return distance_to_infinite_squared(point, &nearest_point);
}
static inline double distance_to_infinite_squared(const Vec3d &point, const Vec3d &a, const Vec3d &b) {
Linef3 line{a, b};
return line.distance_to_infinite_squared(point);
}
Vec3d a;
Vec3d b;
@@ -270,6 +312,8 @@ public:
using Scalar = Vec3d::Scalar;
};
using Linesf3 = std::vector<Linef3>;
BoundingBox get_extents(const Lines &lines);
} // namespace Slic3r

View File

@@ -422,32 +422,23 @@ Points MultiPoint::concave_hull_2d(const Points& pts, const double tolerence)
return min_distance;
}
void MultiPoint3::translate(double x, double y)
void MultiPoint3::translate(const Point3& v)
{
for (Vec3crd &p : points) {
p(0) += coord_t(x);
p(1) += coord_t(y);
}
}
void MultiPoint3::translate(const Point& vector)
{
this->translate(vector(0), vector(1));
for (Point3& pt : points)
pt += v;
}
double MultiPoint3::length() const
{
double len = 0.0;
for (const Line3& line : this->lines())
len += line.length();
const Lines3& lines = this->lines();
double len = 0;
for (auto it = lines.cbegin(); it != lines.cend(); ++it) {
len += it->length();
}
return len;
}
BoundingBox3 MultiPoint3::bounding_box() const
{
return BoundingBox3(points);
}
BoundingBox3 MultiPoint3::bounding_box() const { return BoundingBox3(this->points); }
bool MultiPoint3::remove_duplicate_points()
{
@@ -471,6 +462,75 @@ bool MultiPoint3::remove_duplicate_points()
return false;
}
// Douglas-Peucker simplification for 3D points
Points3 MultiPoint3::_douglas_peucker(const Points3& pts, double tolerance)
{
Points3 result_pts;
double tolerance_sq = tolerance * tolerance;
if (!pts.empty()) {
const Point3* anchor = &pts.front();
size_t anchor_idx = 0;
const Point3* floater = &pts.back();
size_t floater_idx = pts.size() - 1;
result_pts.reserve(pts.size());
result_pts.emplace_back(*anchor);
if (anchor_idx != floater_idx) {
assert(pts.size() > 1);
std::vector<size_t> dpStack;
dpStack.reserve(pts.size());
dpStack.emplace_back(floater_idx);
for (;;) {
double max_dist_sq = 0.0;
size_t furthest_idx = anchor_idx;
// find point furthest from line seg created by (anchor, floater) and note it
for (size_t i = anchor_idx + 1; i < floater_idx; ++i) {
double dist_sq = Line3::distance_to_squared(pts[i], *anchor, *floater);
if (dist_sq > max_dist_sq) {
max_dist_sq = dist_sq;
furthest_idx = i;
}
}
// remove point if less than tolerance
if (max_dist_sq <= tolerance_sq) {
result_pts.emplace_back(*floater);
anchor_idx = floater_idx;
anchor = floater;
assert(dpStack.back() == floater_idx);
dpStack.pop_back();
if (dpStack.empty())
break;
floater_idx = dpStack.back();
} else {
floater_idx = furthest_idx;
dpStack.emplace_back(floater_idx);
}
floater = &pts[floater_idx];
}
}
assert(result_pts.front() == pts.front());
assert(result_pts.back() == pts.back());
#if 0
{
static int iRun = 0;
BoundingBox bbox(pts);
BoundingBox bbox2(result_pts);
bbox.merge(bbox2);
SVG svg(debug_out_path("douglas_peucker_%d.svg", iRun ++).c_str(), bbox);
if (pts.front() == pts.back())
svg.draw(Polygon(pts), "black");
else
svg.draw(Polyline(pts), "black");
if (result_pts.front() == result_pts.back())
svg.draw(Polygon(result_pts), "green", scale_(0.1));
else
svg.draw(Polyline(result_pts), "green", scale_(0.1));
}
#endif
}
return result_pts;
}
BoundingBox get_extents(const MultiPoint &mp)
{
return BoundingBox(mp.points);
@@ -514,4 +574,78 @@ void MultiPoint::symmetric_y(const coord_t &x_axis)
}
}
// MultiPoint3 implementations
void MultiPoint3::rotate(double cos_angle, double sin_angle)
{
for (Point3 &pt : this->points) {
double cur_x = double(pt(0));
double cur_y = double(pt(1));
pt(0) = coord_t(round(cos_angle * cur_x - sin_angle * cur_y));
pt(1) = coord_t(round(cos_angle * cur_y + sin_angle * cur_x));
// Keep Z unchanged
}
}
void MultiPoint3::rotate(double angle, const Point3 &center)
{
double s = sin(angle);
double c = cos(angle);
for (Point3 &pt : points) {
Vec3crd v(pt - center);
pt(0) = (coord_t)round(double(center(0)) + c * v[0] - s * v[1]);
pt(1) = (coord_t)round(double(center(1)) + c * v[1] + s * v[0]);
// Keep Z unchanged from original point
}
}
int MultiPoint3::find_point(const Point &point) const
{
for (const Point3 &pt : this->points)
if (pt.to_point() == point)
return int(&pt - &this->points.front());
return -1; // not found
}
int MultiPoint3::find_point(const Point &point, double scaled_epsilon) const
{
if (scaled_epsilon == 0) return this->find_point(point);
auto dist2_min = std::numeric_limits<double>::max();
auto eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
for (const Point3 &pt : this->points) {
double d2 = (pt.to_point() - point).cast<double>().squaredNorm();
if (d2 < dist2_min) {
idx_min = int(&pt - &this->points.front());
dist2_min = d2;
}
}
return (dist2_min < eps2) ? idx_min : -1;
}
int MultiPoint3::find_point(const Point3 &point) const
{
for (const Point3 &pt : this->points)
if (pt == point)
return int(&pt - &this->points.front());
return -1; // not found
}
int MultiPoint3::find_point(const Point3 &point, double scaled_epsilon) const
{
if (scaled_epsilon == 0) return this->find_point(point);
auto dist2_min = std::numeric_limits<double>::max();
auto eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
for (const Point3 &pt : this->points) {
double d2 = (pt - point).cast<double>().squaredNorm();
if (d2 < dist2_min) {
idx_min = int(&pt - &this->points.front());
dist2_min = d2;
}
}
return (dist2_min < eps2) ? idx_min : -1;
}
}

View File

@@ -119,18 +119,50 @@ class MultiPoint3
public:
Points3 points;
void append(const Vec3crd& point) { this->points.push_back(point); }
void append(const Point3& point) { this->points.push_back(point); }
void append(const Vec3crd& point) { this->points.push_back(Point3(point)); }
void append(const Points3::const_iterator& begin, const Points3::const_iterator& end)
{
this->points.insert(this->points.end(), begin, end);
}
void translate(double x, double y, double z = 0) { this->translate(Point3(coord_t(x), coord_t(y), coord_t(z))); }
void translate(const Point3& vector);
void reverse() { std::reverse(this->points.begin(), this->points.end()); }
void rotate(double angle) { this->rotate(cos(angle), sin(angle)); }
void rotate(double cos_angle, double sin_angle);
void rotate(double angle, const Point3 &center);
Point3& first_point() { return this->points.front(); }
Point3& last_point() { return this->points.back(); }
const Point3& first_point() const { return this->points.front(); }
const Point3& last_point() const { return this->points.back(); }
size_t size() const { return this->points.size(); }
bool empty() const { return this->points.empty(); }
void clear() { this->points.clear(); }
auto begin() { return this->points.begin(); }
auto end() { return this->points.end(); }
auto begin() const { return this->points.begin(); }
auto end() const { return this->points.end(); }
void translate(double x, double y);
void translate(const Point& vector);
virtual Lines3 lines() const = 0;
double length() const;
bool is_valid() const { return this->points.size() >= 2; }
BoundingBox3 bounding_box() const;
// Find a point in the points array
int find_point(const Point &point) const;
int find_point(const Point &point, const double scaled_epsilon) const;
int find_point(const Point3 &point) const;
int find_point(const Point3 &point, const double scaled_epsilon) const;
// Remove exact duplicates, return true if any duplicate has been removed.
bool remove_duplicate_points();
// Douglas-Peucker simplification
static Points3 _douglas_peucker(const Points3 &points, double tolerance);
};
extern BoundingBox get_extents(const MultiPoint &mp);

View File

@@ -206,7 +206,8 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
// Reapply the nearest point search for starting point.
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
if(paths.empty()) continue;
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
Point start_pt = Point(paths.front().first_point().x(), paths.front().first_point().y());
chain_and_reorder_extrusion_paths(paths, &start_pt);
} else {
if (overhangs_reverse && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers) {
// Always reverse if detect overhang wall is not enabled
@@ -216,7 +217,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
ExtrusionPath path(role);
//BBS.
path.polyline = polygon.split_at_first_point();
path.polyline = Polyline3(polygon.split_at_first_point());
path.mm3_per_mm = extrusion_mm3_per_mm;
path.width = extrusion_width;
path.height = (float)perimeter_generator.layer_height;
@@ -441,7 +442,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
Polylines be_clipped;
for (const ExtrusionPath &p : it.second) {
be_clipped.emplace_back(std::move(p.polyline));
be_clipped.emplace_back(p.polyline.to_polyline());
}
BoundingBox extrusion_bboxs = get_extents(be_clipped);
@@ -475,11 +476,13 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
};
std::unordered_map<Point, PointInfo, PointHash> point_occurrence;
for (const ExtrusionPath& path : paths) {
++point_occurrence[path.polyline.first_point()].occurrence;
++point_occurrence[path.polyline.last_point()].occurrence;
Point first_p = path.polyline.first_point().to_point();
Point last_p = path.polyline.last_point().to_point();
++point_occurrence[first_p].occurrence;
++point_occurrence[last_p].occurrence;
if (path.role() == erOverhangPerimeter) {
point_occurrence[path.polyline.first_point()].is_overhang = true;
point_occurrence[path.polyline.last_point()].is_overhang = true;
point_occurrence[first_p].is_overhang = true;
point_occurrence[last_p].is_overhang = true;
}
}
@@ -674,11 +677,17 @@ bool paths_touch(const ExtrusionPath &path_one, const ExtrusionPath &path_two, d
{
AABBTreeLines::LinesDistancer<Line> lines_two{path_two.as_polyline().lines()};
for (size_t pt_idx = 0; pt_idx < path_one.polyline.size(); pt_idx++) {
if (lines_two.distance_from_lines<false>(path_one.polyline.points[pt_idx]) < limit_distance) { return true; }
Point pt = path_one.polyline.points[pt_idx].to_point();
if (lines_two.distance_from_lines<false>(pt) < limit_distance) {
return true;
}
}
AABBTreeLines::LinesDistancer<Line> lines_one{path_one.as_polyline().lines()};
for (size_t pt_idx = 0; pt_idx < path_two.polyline.size(); pt_idx++) {
if (lines_one.distance_from_lines<false>(path_two.polyline.points[pt_idx]) < limit_distance) { return true; }
Point pt = path_two.polyline.points[pt_idx].to_point();
if (lines_one.distance_from_lines<false>(pt) < limit_distance) {
return true;
}
}
return false;
}
@@ -1032,7 +1041,7 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
// polyline)
bool first_overhang_is_closed_and_anchored =
(overhang_region.front().first_point() == overhang_region.front().last_point() &&
!intersection_pl(overhang_region.front().polyline, optimized_lower_slices).empty());
!intersection_pl(overhang_region.front().polyline.to_polyline(), optimized_lower_slices).empty());
auto is_anchored = [&lower_layer_aabb_tree](const ExtrusionPath &path) {
return lower_layer_aabb_tree.distance_from_lines<true>(path.first_point()) <= 0 ||
@@ -1044,7 +1053,7 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
size_t min_dist_idx = 0;
double min_dist = std::numeric_limits<double>::max();
for (size_t i = 0; i < overhang_region.front().polyline.size(); i++) {
Point p = overhang_region.front().polyline[i];
Point p = overhang_region.front().polyline.points[i].to_point();
if (double d = lower_layer_aabb_tree.distance_from_lines<true>(p) < min_dist) {
min_dist = d;
min_dist_idx = i;

View File

@@ -1,6 +1,8 @@
#include "Point.hpp"
#include "Exception.hpp"
#include "Line.hpp"
#include "MultiPoint.hpp"
#include "Polyline.hpp"
#include "Int128.hpp"
#include "BoundingBox.hpp"
#include <algorithm>
@@ -257,4 +259,91 @@ int cross(const Vec2crd &v1, const Vec2crd &v2)
}
// Point3 utility functions for ZAA (Z Anti-Aliasing)
Polyline to_polyline(const Points &points) { return Polyline(points); }
Polyline3 to_polyline(const Points3 &points) { return Polyline3(points); }
Points to_points(const Points3 &points3) {
Points points2;
points2.reserve(points3.size());
for (const Point3 &pt : points3) {
points2.emplace_back(pt.to_point());
}
return points2;
}
Points3 to_points3(const Points& points)
{
Points3 points3;
points3.reserve(points.size());
for (const Point& pt : points) {
points3.emplace_back(pt);
}
return points3;
}
// Point3 method implementations
void Point3::rotate(double angle, const Point3 &center) {
Vec3crd diff = *this - center;
Point3 temp(diff.x(), diff.y(), diff.z());
temp.rotate(angle);
Vec3crd sum = temp + center;
*this = Point3(sum.x(), sum.y(), sum.z());
}
int Point3::nearest_point_index(const Points &points) const {
return this->to_point().nearest_point_index(points);
}
bool Point3::nearest_point(const Points &points, Point3* point) const {
Point pt2d;
bool result = this->to_point().nearest_point(points, &pt2d);
if (result && point) {
*point = Point3(pt2d, this->z());
}
return result;
}
double Point3::ccw(const Point3 &p1, const Point3 &p2) const {
return this->to_point().ccw(p1.to_point(), p2.to_point());
}
double Point3::ccw(const Line3 &line) const {
// Convert to 2D and use existing Point ccw implementation
Point a2d(line.a.x(), line.a.y());
Point b2d(line.b.x(), line.b.y());
return this->to_point().ccw(Line(a2d, b2d));
}
double Point3::ccw_angle(const Point3 &p1, const Point3 &p2) const {
return this->to_point().ccw_angle(p1.to_point(), p2.to_point());
}
Point3 Point3::projection_onto(const MultiPoint3 &poly) const {
// TODO: Implement proper 3D projection when MultiPoint3 conversion methods are ready
// For now, stub implementation
throw RuntimeError("Point3::projection_onto(MultiPoint3) not implemented yet");
return *this;
}
Point3 Point3::projection_onto(const Line3 &line) const {
// Project in 2D plane and interpolate Z
Point pt2d = this->to_point();
Point line_a(line.a.x(), line.a.y());
Point line_b(line.b.x(), line.b.y());
Line line2d(line_a, line_b);
Point proj2d = pt2d.projection_onto(line2d);
// Interpolate Z coordinate
double line_len = line.length();
if (line_len < EPSILON) {
return Point3(proj2d, line.a.z());
}
double dist_from_a = (proj2d - line_a).cast<double>().norm();
double t = dist_from_a / line_len;
t = std::clamp(t, 0.0, 1.0);
coord_t z = coord_t(line.a.z() + t * (line.b.z() - line.a.z()));
return Point3(proj2d, z);
}
}

View File

@@ -21,8 +21,13 @@ namespace Slic3r {
class BoundingBox;
class BoundingBoxf;
class Line;
class Line3;
class MultiPoint;
class MultiPoint3;
class Point;
class Point3;
class Polyline;
class Polyline3;
using Vector = Point;
// Base template for eigen derived vectors
@@ -57,7 +62,7 @@ using PointsAllocator = tbb::scalable_allocator<BaseType>;
using Points = std::vector<Point, PointsAllocator<Point>>;
using PointPtrs = std::vector<Point*>;
using PointConstPtrs = std::vector<const Point*>;
using Points3 = std::vector<Vec3crd>;
using Points3 = std::vector<Point3, PointsAllocator<Point3>>;
using Pointfs = std::vector<Vec2d>;
using Vec2ds = std::vector<Vec2d>;
using Pointf3s = std::vector<Vec3d>;
@@ -79,6 +84,12 @@ using Transform2d = Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAli
using Transform3f = Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign>;
using Transform3d = Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign>;
// Utility functions for Point/Polyline conversion
Polyline to_polyline(const Points &points);
Polyline3 to_polyline(const Points3 &points);
Points to_points(const Points3 &points);
Points3 to_points3(const Points& points);
// using ColorRGBA = std::array<float, 4>;
// I don't know why Eigen::Transform::Identity() return a const object...
template<int N, class T> Transform<N, T> identity() { return Transform<N, T>::Identity(); }
@@ -258,6 +269,118 @@ inline Point operator* (const Point& l, const double& r)
return { coord_t(l.x() * r), coord_t(l.y() * r) };
}
// Point3 class - 3D point with Z coordinate for non-planar printing (ZAA)
class Point3 : public Vec3crd {
public:
using coord_type = coord_t;
Point3() : Vec3crd(0, 0, 0) {}
Point3(int32_t x, int32_t y, int32_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
Point3(int64_t x, int64_t y, int64_t z = 0) : Vec3crd(coord_t(x), coord_t(y), coord_t(z)) {}
Point3(double x, double y, double z = 0.0) : Vec3crd(coord_t(std::round(x)), coord_t(std::round(y)), coord_t(std::round(z))) {}
Point3(const Point3 &rhs) { *this = rhs; }
explicit Point3(const Vec2crd& vec2crd, coord_t z = 0) : Vec3crd(vec2crd.x(), vec2crd.y(), z) {}
explicit Point3(const Vec3crd &vec3crd) : Vec3crd(vec3crd) {}
// This constructor allows you to construct Point from Eigen expressions
template<typename OtherDerived>
explicit Point3(const Eigen::MatrixBase<OtherDerived> &other) : Vec3crd(other) {}
static Point3 new_scale(coordf_t x, coordf_t y, coordf_t z) {
return Point3(coord_t(scale_(x)), coord_t(scale_(y)), coord_t(scale_(z)));
}
static Point3 new_scale(const Vec3d &v) {
return Point3(coord_t(scale_(v.x())), coord_t(scale_(v.y())), coord_t(scale_(v.z())));
}
static Point3 new_scale(const Vec3f &v) {
return Point3(coord_t(scale_(v.x())), coord_t(scale_(v.y())), coord_t(scale_(v.z())));
}
// Assignment operator for Eigen expressions
template<typename OtherDerived>
Point3& operator=(const Eigen::MatrixBase<OtherDerived> &other)
{
this->Vec3crd::operator=(other);
return *this;
}
Point3& operator+=(const Point3& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); this->z() += rhs.z(); return *this; }
Point3& operator-=(const Point3& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); this->z() -= rhs.z(); return *this; }
Point3& operator*=(const double &rhs) {
this->x() = coord_t(this->x() * rhs);
this->y() = coord_t(this->y() * rhs);
this->z() = coord_t(this->z() * rhs);
return *this;
}
Point3 operator*(const double &rhs) const { return Point3(this->x() * rhs, this->y() * rhs, this->z() * rhs); }
bool both_comp(const Point3 &rhs, const std::string& op) {
if (op == ">")
return this->x() > rhs.x() && this->y() > rhs.y();
else if (op == "<")
return this->x() < rhs.x() && this->y() < rhs.y();
return false;
}
bool any_comp(const Point3 &rhs, const std::string &op)
{
if (op == ">")
return this->x() > rhs.x() || this->y() > rhs.y();
else if (op == "<")
return this->x() < rhs.x() || this->y() < rhs.y();
return false;
}
bool any_comp(const coord_t val, const std::string &op)
{
if (op == ">")
return this->x() > val || this->y() > val;
else if (op == "<")
return this->x() < val || this->y() < val;
return false;
}
void rotate(double angle) { this->rotate(std::cos(angle), std::sin(angle)); }
void rotate(double cos_a, double sin_a) {
double cur_x = (double)this->x();
double cur_y = (double)this->y();
this->x() = (coord_t)round(cos_a * cur_x - sin_a * cur_y);
this->y() = (coord_t)round(cos_a * cur_y + sin_a * cur_x);
}
void rotate(double angle, const Point3 &center);
Point3 rotated(double angle) const { Point3 res(*this); res.rotate(angle); return res; }
Point3 rotated(double cos_a, double sin_a) const { Point3 res(*this); res.rotate(cos_a, sin_a); return res; }
Point3 rotated(double angle, const Point3 &center) const { Point3 res(*this); res.rotate(angle, center); return res; }
Point3 rotate_90_degree_ccw() const { return Point3(-this->y(), this->x(), this->z()); }
int nearest_point_index(const Points &points) const;
bool nearest_point(const Points &points, Point3* point) const;
double ccw(const Point3 &p1, const Point3 &p2) const;
double ccw(const Line3 &line) const;
double ccw_angle(const Point3 &p1, const Point3 &p2) const;
Point3 projection_onto(const MultiPoint3 &poly) const;
Point3 projection_onto(const Line3 &line) const;
// Convert to 2D Point by dropping Z coordinate
Point to_point() const {
return Point(this->x(), this->y());
}
double distance_to(const Point3 &point) const { return (point - *this).cast<double>().norm(); }
};
// Utility function to convert Points3 to Points
inline void append_points(Points &dst, const Points3 &src) {
std::transform(src.begin(), src.end(),
std::back_inserter(dst),
[](const Point3 &pt) {
return pt.to_point();
});
}
inline Point3 operator* (const Point3& l, const double& r)
{
return { coord_t(l.x() * r), coord_t(l.y() * r), coord_t(l.z() * r) };
}
inline std::ostream &operator<<(std::ostream &os, const Point &pt)
{
os << unscale_(pt.x()) << "," << unscale_(pt.y());
@@ -300,6 +423,12 @@ inline Point lerp(const Point &a, const Point &b, double t)
return ((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>();
}
inline Point3 lerp(const Point3& a, const Point3& b, double t)
{
assert((t >= -EPSILON) && (t <= 1. + EPSILON));
return Point3(((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>());
}
// if IncludeBoundary, then a bounding box is defined even for a single point.
// otherwise a bounding box is only defined if it has a positive area.
template<bool IncludeBoundary = false>

View File

@@ -38,6 +38,9 @@ Polyline Polygon::split_at_vertex(const Point &point) const
Polyline Polygon::split_at_index(int index) const
{
Polyline polyline;
if (this->points.empty())
return polyline;
polyline.points.reserve(this->points.size() + 1);
for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
polyline.points.push_back(*it);

View File

@@ -612,6 +612,28 @@ std::pair<int, Point> foot_pt(const Points &polyline, const Point &pt)
return std::make_pair(int(it_proj - polyline.begin()) - 1, foot_pt_min);
}
std::pair<int, Point3> foot_pt(const Points3 &polyline, const Point3 &pt)
{
if (polyline.size() < 2) return std::make_pair(-1, Point3(0, 0, 0));
auto d2_min = std::numeric_limits<double>::max();
Point3 foot_pt_min;
Point3 prev = polyline.front();
auto it = polyline.begin();
auto it_proj = polyline.begin();
for (++it; it != polyline.end(); ++it) {
Point3 foot_pt = pt.projection_onto(Line3(prev, *it));
double d2 = (foot_pt - pt).cast<double>().squaredNorm();
if (d2 < d2_min) {
d2_min = d2;
foot_pt_min = foot_pt;
it_proj = it;
}
prev = *it;
}
return std::make_pair(int(it_proj - polyline.begin()) - 1, foot_pt_min);
}
ThickLines ThickPolyline::thicklines() const
{
ThickLines lines;
@@ -639,15 +661,383 @@ void ThickPolyline::start_at_index(int index)
Lines3 Polyline3::lines() const
{
Lines3 lines;
if (points.size() >= 2)
{
lines.reserve(points.size() - 1);
for (Points3::const_iterator it = points.begin(); it != points.end() - 1; ++it)
{
if (this->points.size() >= 2) {
lines.reserve(this->points.size() - 1);
for (Points3::const_iterator it = this->points.begin(); it != this->points.end() - 1; ++it) {
lines.emplace_back(*it, *(it + 1));
}
}
return lines;
}
Polyline Polyline3::to_polyline() const
{
Polyline out;
out.points.reserve(this->points.size());
for (const Point3 &point : this->points) {
out.points.emplace_back(point.x(), point.y());
}
return out;
}
void Polyline3::clip_end(double distance)
{
bool last_point_inserted = false;
size_t remove_after_index = MultiPoint3::size();
while (distance > 0) {
Vec3d last_point = this->last_point().cast<double>();
this->points.pop_back();
remove_after_index--;
if (this->points.empty()) {
this->fitting_result.clear();
return;
}
Vec3d v = this->last_point().cast<double>() - last_point;
double lsqr = v.squaredNorm();
if (lsqr > distance * distance) {
this->points.emplace_back((last_point + v * (distance / sqrt(lsqr))).cast<coord_t>());
last_point_inserted = true;
break;
}
distance -= sqrt(lsqr);
}
// BBS: don't need to clip fitting result if it's empty
if (fitting_result.empty())
return;
while (!fitting_result.empty() && fitting_result.back().start_point_index >= remove_after_index)
fitting_result.pop_back();
if (!fitting_result.empty()) {
// BBS: last remaining segment is arc move, then clip the arc at last point
if (fitting_result.back().path_type == EMovePathType::Arc_move_ccw ||
fitting_result.back().path_type == EMovePathType::Arc_move_cw) {
if (fitting_result.back().arc_data.clip_end(this->last_point().to_point()))
// BBS: succeed to clip arc, then update the last point
// TODO: fix z parameter
this->points.back() = Point3(fitting_result.back().arc_data.end_point, this->points.back().z());
else
// BBS: Failed to clip arc, then back to linear move
fitting_result.back().path_type = EMovePathType::Linear_move;
}
fitting_result.back().end_point_index = this->points.size() - 1;
}
}
void Polyline3::simplify(double tolerance)
{
this->points = MultiPoint3::_douglas_peucker(this->points, tolerance);
this->fitting_result.clear();
}
void Polyline3::simplify_by_fitting_arc(double tolerance)
{
// BBS: do arc fit first, then use DP simplify to handle the straight part to reduce point.
Points points_2d = to_points(this->points);
ArcFitter::do_arc_fitting_and_simplify(points_2d, this->fitting_result, tolerance);
this->points = to_points3(points_2d);
}
void Polyline3::reverse()
{
// BBS: reverse points
MultiPoint3::reverse();
// BBS: reverse the fitting_result
if (!this->fitting_result.empty()) {
for (size_t i = 0; i < this->fitting_result.size(); i++) {
std::swap(fitting_result[i].start_point_index, fitting_result[i].end_point_index);
fitting_result[i].start_point_index = MultiPoint3::size() - 1 - fitting_result[i].start_point_index;
fitting_result[i].end_point_index = MultiPoint3::size() - 1 - fitting_result[i].end_point_index;
if (fitting_result[i].is_arc_move())
fitting_result[i].reverse_arc_path();
}
std::reverse(this->fitting_result.begin(), this->fitting_result.end());
}
}
bool Polyline3::split_at_index(const size_t index, Polyline3 *p1, Polyline3 *p2) const
{
if (index > this->size() - 1)
return false;
if (index == 0) {
p1->clear();
p1->append(this->first_point());
*p2 = *this;
} else if (index == this->size() - 1) {
p2->clear();
p2->append(this->last_point());
*p1 = *this;
} else {
// BBS: spilit first part
p1->clear();
p1->points.reserve(index + 1);
p1->points.insert(p1->begin(), this->begin(), this->begin() + index + 1);
Point3 new_endpoint;
if (this->split_fitting_result_before_index(index, new_endpoint, p1->fitting_result))
p1->points.back() = new_endpoint;
p2->clear();
p2->points.reserve(this->size() - index);
p2->points.insert(p2->begin(), this->begin() + index, this->end());
Point3 new_startpoint;
if (this->split_fitting_result_after_index(index, new_startpoint, p2->fitting_result))
p2->points.front() = new_startpoint;
}
return true;
}
void Polyline3::append(const Point3& point)
{
// // Don't append if same as last point
// if (!this->empty() && this->last_point() == point)
// return;
// this->points.push_back(point);
// append_fitting_result_after_append_points();
// BBS: don't need to append same point
if (!this->empty() && this->last_point() == point)
return;
MultiPoint3::append(point);
append_fitting_result_after_append_points();
}
void Polyline3::append(const Polyline3& src)
{
if (!src.is_valid()) return;
if (this->points.empty()) {
this->points = src.points;
this->fitting_result = src.fitting_result;
} else {
// BBS: append the first point to create connection first, update the fitting date as well
this->append(src.points[0]);
// BBS: append a polyline which has fitting data to a polyline without fitting data.
// Then create a fake fitting data first, so that we can keep the fitting data in last polyline
if (this->fitting_result.empty() && !src.fitting_result.empty()) {
this->fitting_result.emplace_back(PathFittingData{0, this->points.size() - 1, EMovePathType::Linear_move, ArcSegment()});
}
// BBS: then append the remain points
MultiPoint3::append(src.points.begin() + 1, src.points.end());
// BBS: finally append the fitting data
append_fitting_result_after_append_polyline(src);
}
}
void Polyline3::append_before(const Point3& point)
{
// BBS: don't need to append same point
if (!this->empty() && this->first_point() == point)
return;
if (this->size() == 1) {
this->fitting_result.clear();
MultiPoint3::append(point);
MultiPoint3::reverse();
} else {
this->reverse();
this->append(point);
this->reverse();
}
}
void Polyline3::split_at(Point& point, Polyline3* p1, Polyline3* p2) const
{
if (this->points.empty()) return;
// 0 judge whether the point is on the polyline
int index = this->find_point(point);
if (index != -1) {
// BBS: the spilit point is on the polyline, then easy
split_at_index(index, p1, p2);
point = p1->is_valid() ? p1->last_point().to_point() : p2->first_point().to_point();
return;
}
// 1 find the line to split at
size_t line_idx = 0;
Point p = this->first_point().to_point();
double min = (p - point).cast<double>().norm();
Lines3 lines = this->lines();
for (Lines3::const_iterator line = lines.begin(); line != lines.end(); ++line) {
Point p_tmp = point.projection_onto(line->to_line());
if ((p_tmp - point).cast<double>().norm() < min) {
p = p_tmp;
min = (p - point).cast<double>().norm();
line_idx = line - lines.begin();
}
}
// 2 judge whether the cloest point is one vertex of polyline.
// and spilit the polyline at different index
index = this->find_point(p);
if (index != -1) {
this->split_at_index(index, p1, p2);
p1->append(Point3(point, p1->last_point().z()));
p2->append_before(Point3(point, p2->first_point().z()));
} else {
Polyline3 temp;
this->split_at_index(line_idx, p1, &temp);
p1->append(Point3(point, p1->last_point().z()));
this->split_at_index(line_idx + 1, &temp, p2);
p2->append_before(Point3(point, p2->first_point().z()));
}
}
void Polyline3::split_at(Point3 &point, Polyline3* p1, Polyline3* p2) const {
Point p = point.to_point();
this->split_at(p, p1, p2);
point = Point3(p, point.z());
}
bool Polyline3::split_at_length(const double length, Polyline3 *p1, Polyline3 *p2) const {
if (this->points.empty()) return false;
if (length < 0 || length > this->length()) {
return false;
}
if (length < SCALED_EPSILON) {
p1->clear();
p1->append(this->first_point());
*p2 = *this;
} else if (is_approx(length, this->length(), SCALED_EPSILON)) {
p2->clear();
p2->append(this->last_point());
*p1 = *this;
} else {
// 1 find the line to split at
size_t line_idx = 0;
double acc_length = 0;
Point3 p = this->first_point();
for (const auto& l : this->lines()) {
p = l.b;
const double current_length = l.length();
if (acc_length + current_length >= length) {
p = lerp(l.a, l.b, (length - acc_length) / current_length);
break;
}
acc_length += current_length;
line_idx++;
}
// 2 judge whether the cloest point is one vertex of polyline.
// and spilit the polyline at different index
int index = this->find_point(p);
if (index != -1) {
this->split_at_index(index, p1, p2);
} else {
Polyline3 temp;
this->split_at_index(line_idx, p1, &temp);
p1->append(p);
this->split_at_index(line_idx + 1, &temp, p2);
p2->append_before(p);
}
}
return true;
}
bool Polyline3::split_fitting_result_before_index(size_t index, Point3& new_endpoint, std::vector<PathFittingData>& data) const
{
data.clear();
new_endpoint = this->points[index];
if (!this->fitting_result.empty()) {
// BBS: max size
data.reserve(this->fitting_result.size());
// BBS: save fitting result before index
for (size_t i = 0; i < this->fitting_result.size(); i++) {
if (this->fitting_result[i].start_point_index < index)
data.push_back(this->fitting_result[i]);
else
break;
}
if (!data.empty()) {
// BBS: need to clip the arc and generate new end point
if (data.back().is_arc_move() && data.back().end_point_index > index) {
if (!data.back().arc_data.clip_end(this->points[index].to_point()))
// BBS: failed to clip arc, then return to be linear move
data.back().path_type = EMovePathType::Linear_move;
else
// BBS: succeed to clip arc, then update and return the new end point
new_endpoint = Point3(data.back().arc_data.end_point, 0);
}
data.back().end_point_index = index;
}
data.shrink_to_fit();
return true;
}
return false;
}
bool Polyline3::split_fitting_result_after_index(size_t index, Point3& new_startpoint, std::vector<PathFittingData>& data) const
{
data.clear();
new_startpoint = this->points[index];
if (!this->fitting_result.empty()) {
data.reserve(this->fitting_result.size());
for (size_t i = 0; i < this->fitting_result.size(); i++) {
if (this->fitting_result[i].end_point_index > index)
data.push_back(this->fitting_result[i]);
}
if (!data.empty()) {
for (size_t i = 0; i < data.size(); i++) {
if (i != 0) {
data[i].start_point_index -= index;
data[i].end_point_index -= index;
} else {
data[i].end_point_index -= index;
// BBS: need to clip the arc and generate new start point
if (data.front().is_arc_move() && data.front().start_point_index < index) {
if (!data.front().arc_data.clip_start(this->points[index].to_point()))
// BBS: failed to clip arc, then return to be linear move
data.front().path_type = EMovePathType::Linear_move;
else
// BBS: succeed to clip arc, then update and return the new start point
new_startpoint = Point3(data.front().arc_data.start_point, 0);
}
data[i].start_point_index = 0;
}
}
}
data.shrink_to_fit();
return true;
}
return false;
}
void Polyline3::append_fitting_result_after_append_points()
{
if (!fitting_result.empty()) {
if (fitting_result.back().is_linear_move()) {
fitting_result.back().end_point_index = this->points.size() - 1;
} else {
size_t new_start = fitting_result.back().end_point_index;
size_t new_end = this->points.size() - 1;
if (new_start != new_end)
fitting_result.emplace_back(PathFittingData{new_start, new_end, EMovePathType::Linear_move, ArcSegment()});
}
}
}
void Polyline3::append_fitting_result_after_append_polyline(const Polyline3& src)
{
if (!this->fitting_result.empty()) {
// BBS: offset and save the fitting_result from src polyline
if (!src.fitting_result.empty()) {
size_t old_size = this->fitting_result.size();
size_t index_offset = this->fitting_result.back().end_point_index;
this->fitting_result.insert(this->fitting_result.end(), src.fitting_result.begin(), src.fitting_result.end());
for (size_t i = old_size; i < this->fitting_result.size(); i++) {
this->fitting_result[i].start_point_index += index_offset;
this->fitting_result[i].end_point_index += index_offset;
}
} else {
// BBS: the append polyline has no fitting data, then append as linear move directly
size_t new_start = this->fitting_result.back().end_point_index;
size_t new_end = this->size() - 1;
if (new_start != new_end)
this->fitting_result.emplace_back(PathFittingData{new_start, new_end, EMovePathType::Linear_move, ArcSegment()});
}
}
}
}

View File

@@ -251,6 +251,7 @@ bool remove_degenerate(Polylines &polylines);
// Returns index of a segment of a polyline and foot point of pt on polyline.
std::pair<int, Point> foot_pt(const Points &polyline, const Point &pt);
std::pair<int, Point3> foot_pt(const Points3 &polyline, const Point3 &pt);
class ThickPolyline : public Polyline {
public:
@@ -290,7 +291,63 @@ inline ThickPolylines to_thick_polylines(Polylines&& polylines, const coordf_t w
class Polyline3 : public MultiPoint3
{
public:
Polyline3() {}
explicit Polyline3(const Points3 &points) { this->points = points; }
explicit Polyline3(const Polyline &poly, coord_t z = 0) {
this->points.reserve(poly.points.size());
for (const Point &pt : poly.points) {
this->points.emplace_back(pt.x(), pt.y(), z);
}
}
virtual Lines3 lines() const;
// Convert to 2D Polyline by dropping Z coordinates
Polyline to_polyline() const;
// Clip the end of the polyline by a distance
void clip_end(double distance);
// Simplify polyline using Douglas-Peucker algorithm
void simplify(double tolerance);
// Simplify by arc fitting (for ZAA arc fitting support)
void simplify_by_fitting_arc(double tolerance);
// Reverse the polyline
void reverse();
// Split polyline at given index
bool split_at_index(const size_t index, Polyline3 *p1, Polyline3 *p2) const;
// Split polyline at a given point (2D)
void split_at(Point &point, Polyline3* p1, Polyline3* p2) const;
// Split polyline at a given point (3D)
void split_at(Point3 &point, Polyline3* p1, Polyline3* p2) const;
// Split polyline at a given length
bool split_at_length(const double length, Polyline3 *p1, Polyline3 *p2) const;
// Append a single point
void append(const Point3& point);
// Append another Polyline3
void append(const Polyline3& src);
// Append before (prepend)
void append_before(const Point3& point);
// Arc fitting support - fitting_result stores arc path data
// This is populated by simplify_by_fitting_arc()
// Uses the global PathFittingData from ArcFitter.hpp
std::vector<PathFittingData> fitting_result;
private:
void append_fitting_result_after_append_points();
void append_fitting_result_after_append_polyline(const Polyline3& src);
bool split_fitting_result_before_index(size_t index, Point3& new_endpoint, std::vector<PathFittingData>& result) const;
bool split_fitting_result_after_index(size_t index, Point3& new_startpoint, std::vector<PathFittingData>& result) const;
};
typedef std::vector<Polyline3> Polylines3;

View File

@@ -974,16 +974,74 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle)
return false;
}
static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness",
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction",
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density",
"align_infill_direction_to_model", "extra_solid_infills",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_angle_fixed", "ironing_inset",
"support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing",
static std::vector<std::string> s_Preset_print_options{
"layer_height",
"initial_layer_print_height",
"wall_loops",
"alternate_extra_wall",
"slice_closing_radius",
"spiral_mode",
"spiral_mode_smooth",
"spiral_mode_max_xy_smoothing",
"spiral_starting_flow_ratio",
"spiral_finishing_flow_ratio",
"slicing_mode",
"top_shell_layers",
"top_shell_thickness",
"top_surface_density",
"bottom_surface_density",
"bottom_shell_layers",
"bottom_shell_thickness",
"extra_perimeters_on_overhangs",
"ensure_vertical_shell_thickness",
"reduce_crossing_wall",
"detect_thin_wall",
"detect_overhang_wall",
"overhang_reverse",
"overhang_reverse_threshold",
"overhang_reverse_internal_only",
"wall_direction",
"seam_position",
"staggered_inner_seams",
"wall_sequence",
"is_infill_first",
"sparse_infill_density",
"fill_multiline",
"sparse_infill_pattern",
"lateral_lattice_angle_1",
"lateral_lattice_angle_2",
"infill_overhang_angle",
"top_surface_pattern",
"bottom_surface_pattern",
"infill_direction",
"solid_infill_direction",
"counterbore_hole_bridging",
"infill_shift_step",
"sparse_infill_rotate_template",
"solid_infill_rotate_template",
"symmetric_infill_y_axis",
"skeleton_infill_density",
"infill_lock_depth",
"skin_infill_depth",
"skin_infill_density",
"align_infill_direction_to_model",
"extra_solid_infills",
"minimum_sparse_infill_area",
"reduce_infill_retraction",
"internal_solid_infill_pattern",
"gap_fill_target",
"ironing_type",
"ironing_pattern",
"ironing_flow",
"ironing_speed",
"ironing_spacing",
"ironing_angle",
"ironing_angle_fixed",
"ironing_inset",
"support_ironing",
"support_ironing_pattern",
"support_ironing_flow",
"support_ironing_spacing",
"max_travel_detour_distance",
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence",
"max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only",
@@ -995,54 +1053,220 @@ static std::vector<std::string> s_Preset_print_options {
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
"support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style",
// BBS
"print_extruder_id", "print_extruder_variant",
"print_extruder_id",
"print_extruder_variant",
"independent_support_layer_height",
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "thick_internal_bridges","dont_filter_internal_bridges","enable_extra_bridge_layer", "max_bridge_length", "print_sequence", "print_order", "support_remove_small_overhang",
"filename_format", "wall_filament", "support_bottom_z_distance",
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body",
"ooze_prevention", "standby_temperature_delta", "preheat_time","preheat_steps", "interface_shells", "line_width", "initial_layer_line_width", "inner_wall_line_width",
"outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
"skin_infill_line_width","skeleton_infill_line_width",
"top_surface_line_width", "support_line_width", "infill_wall_overlap","top_bottom_infill_wall_overlap", "bridge_flow", "internal_bridge_flow",
"elefant_foot_compensation", "elefant_foot_compensation_layers", "elefant_foot_layers_density", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower", "prime_tower_enable_framework",
"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_volume",
"support_angle",
"support_interface_top_layers",
"support_interface_bottom_layers",
"support_interface_pattern",
"support_interface_spacing",
"support_interface_loop_pattern",
"support_top_z_distance",
"support_on_build_plate_only",
"support_critical_regions_only",
"bridge_no_support",
"thick_bridges",
"thick_internal_bridges",
"dont_filter_internal_bridges",
"enable_extra_bridge_layer",
"max_bridge_length",
"print_sequence",
"print_order",
"support_remove_small_overhang",
"filename_format",
"wall_filament",
"support_bottom_z_distance",
"sparse_infill_filament",
"solid_infill_filament",
"support_filament",
"support_interface_filament",
"support_interface_not_for_body",
"ooze_prevention",
"standby_temperature_delta",
"preheat_time",
"preheat_steps",
"interface_shells",
"line_width",
"initial_layer_line_width",
"inner_wall_line_width",
"outer_wall_line_width",
"sparse_infill_line_width",
"internal_solid_infill_line_width",
"skin_infill_line_width",
"skeleton_infill_line_width",
"top_surface_line_width",
"support_line_width",
"infill_wall_overlap",
"top_bottom_infill_wall_overlap",
"bridge_flow",
"internal_bridge_flow",
"elefant_foot_compensation",
"elefant_foot_compensation_layers",
"elefant_foot_layers_density",
"xy_contour_compensation",
"xy_hole_compensation",
"resolution",
"enable_prime_tower",
"prime_tower_enable_framework",
"prime_tower_width",
"prime_tower_brim_width",
"prime_tower_skip_points",
"prime_volume",
"prime_tower_infill_gap",
"prime_tower_flat_ironing",
"enable_tower_interface_features",
"enable_tower_interface_cooldown_during_tower",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support",
"tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter",
"tree_support_branch_diameter", "tree_support_branch_diameter_angle",
"detect_narrow_internal_solid_infill",
"gcode_add_line_number", "enable_arc_fitting", "precise_z_height", "infill_combination","infill_combination_max_layer_height", /*"adaptive_layer_height",*/
"support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
"initial_layer_infill_speed", "only_one_wall_top",
"timelapse_type",
"wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width", "post_process", "process_change_extrusion_role_gcode",
"min_length_factor", "wall_maximum_resolution", "wall_maximum_deviation",
"small_perimeter_speed", "small_perimeter_threshold","bridge_angle","internal_bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk","default_junction_deviation",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"set_other_flow_ratios", "first_layer_flow_ratio", "outer_wall_flow_ratio", "inner_wall_flow_ratio", "overhang_flow_ratio", "sparse_infill_flow_ratio", "internal_solid_infill_flow_ratio", "gap_fill_flow_ratio", "support_flow_ratio", "support_interface_flow_ratio",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop",
"bridge_density","internal_bridge_density", "precise_outer_wall", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "initial_layer_travel_acceleration", "initial_layer_travel_jerk", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width",
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size" ,"notes",
"wipe_tower_cone_angle", "wipe_tower_extra_spacing","wipe_tower_max_purge_speed",
"wipe_tower_wall_type", "wipe_tower_extra_rib_length", "wipe_tower_rib_width", "wipe_tower_fillet_wall",
"wipe_tower_filament", "wiping_volumes_extruders","wipe_tower_bridging", "wipe_tower_extra_flow","single_extruder_multi_material_priming",
"wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic",
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth",
"small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model",
"enable_wrapping_detection",
"seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold",
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order",
"wipe_tower_no_sparse_layers",
"compatible_printers",
"compatible_printers_condition",
"inherits",
"flush_into_infill",
"flush_into_objects",
"flush_into_support",
"tree_support_branch_angle",
"tree_support_angle_slow",
"tree_support_wall_count",
"tree_support_top_rate",
"tree_support_branch_distance",
"tree_support_tip_diameter",
"tree_support_branch_diameter",
"tree_support_branch_diameter_angle",
"detect_narrow_internal_solid_infill",
"gcode_add_line_number",
"enable_arc_fitting",
"precise_z_height",
"infill_combination",
"infill_combination_max_layer_height", /*"adaptive_layer_height",*/
"support_bottom_interface_spacing",
"enable_overhang_speed",
"slowdown_for_curled_perimeters",
"overhang_1_4_speed",
"overhang_2_4_speed",
"overhang_3_4_speed",
"overhang_4_4_speed",
"initial_layer_infill_speed",
"only_one_wall_top",
"timelapse_type",
"wall_generator",
"wall_transition_length",
"wall_transition_filter_deviation",
"wall_transition_angle",
"wall_distribution_count",
"min_feature_size",
"min_bead_width",
"post_process",
"process_change_extrusion_role_gcode",
"min_length_factor",
"wall_maximum_resolution",
"wall_maximum_deviation",
"small_perimeter_speed",
"small_perimeter_threshold",
"bridge_angle",
"internal_bridge_angle",
"filter_out_gap_fill",
"travel_acceleration",
"inner_wall_acceleration",
"min_width_top_surface",
"default_jerk",
"outer_wall_jerk",
"inner_wall_jerk",
"infill_jerk",
"top_surface_jerk",
"initial_layer_jerk",
"travel_jerk",
"default_junction_deviation",
"top_solid_infill_flow_ratio",
"bottom_solid_infill_flow_ratio",
"only_one_wall_first_layer",
"print_flow_ratio",
"seam_gap",
"set_other_flow_ratios",
"first_layer_flow_ratio",
"outer_wall_flow_ratio",
"inner_wall_flow_ratio",
"overhang_flow_ratio",
"sparse_infill_flow_ratio",
"internal_solid_infill_flow_ratio",
"gap_fill_flow_ratio",
"support_flow_ratio",
"support_interface_flow_ratio",
"role_based_wipe_speed",
"wipe_speed",
"accel_to_decel_enable",
"accel_to_decel_factor",
"wipe_on_loops",
"wipe_before_external_loop",
"bridge_density",
"internal_bridge_density",
"precise_outer_wall",
"bridge_acceleration",
"sparse_infill_acceleration",
"internal_solid_infill_acceleration",
"tree_support_auto_brim",
"tree_support_brim_width",
"gcode_comments",
"gcode_label_objects",
"initial_layer_travel_speed",
"initial_layer_travel_acceleration",
"initial_layer_travel_jerk",
"exclude_object",
"slow_down_layers",
"infill_anchor",
"infill_anchor_max",
"initial_layer_min_bead_width",
"make_overhang_printable",
"make_overhang_printable_angle",
"make_overhang_printable_hole_size",
"notes",
"wipe_tower_cone_angle",
"wipe_tower_extra_spacing",
"wipe_tower_max_purge_speed",
"wipe_tower_wall_type",
"wipe_tower_extra_rib_length",
"wipe_tower_rib_width",
"wipe_tower_fillet_wall",
"wipe_tower_filament",
"wiping_volumes_extruders",
"wipe_tower_bridging",
"wipe_tower_extra_flow",
"single_extruder_multi_material_priming",
"wipe_tower_rotation_angle",
"tree_support_branch_distance_organic",
"tree_support_branch_diameter_organic",
"tree_support_branch_angle_organic",
"hole_to_polyhole",
"hole_to_polyhole_threshold",
"hole_to_polyhole_twisted",
"mmu_segmented_region_max_width",
"mmu_segmented_region_interlocking_depth",
"small_area_infill_flow_compensation",
"small_area_infill_flow_compensation_model",
"enable_wrapping_detection",
"seam_slope_type",
"seam_slope_conditional",
"scarf_angle_threshold",
"scarf_joint_speed",
"scarf_joint_flow_ratio",
"seam_slope_start_height",
"seam_slope_entire_loop",
"seam_slope_min_length",
"seam_slope_steps",
"seam_slope_inner_walls",
"scarf_overhang_threshold",
"interlocking_beam",
"interlocking_orientation",
"interlocking_beam_layer_count",
"interlocking_depth",
"interlocking_boundary_avoidance",
"interlocking_beam_width",
"calib_flowrate_topinfill_special_order",
// Z Anti-Aliasing (ZAA)
"zaa_enabled",
"zaa_minimize_perimeter_height",
"zaa_dont_alternate_fill_direction",
"zaa_min_z",
"ironing_expansion",
};
static std::vector<std::string> s_Preset_filament_options {/*"filament_colour", */ "default_filament_colour", "required_nozzle_HRC", "filament_diameter", "pellet_flow_coefficient", "volumetric_speed_coefficients", "filament_type",

View File

@@ -2213,6 +2213,17 @@ void Print::process(long long *time_cost_with_cache, bool use_cache)
}
}
// Z-Contouring
for (PrintObject *obj : m_objects) {
bool need_contouring = need_slicing_objects.count(obj) != 0 && obj->need_z_contouring();
if (need_contouring) {
obj->contour_z();
} else {
if (obj->set_started(posContouring))
obj->set_done(posContouring);
}
}
tbb::parallel_for(tbb::blocked_range<int>(0, int(m_objects.size())),
[this, need_slicing_objects](const tbb::blocked_range<int>& range) {
for (int i = range.begin(); i < range.end(); i++) {
@@ -2251,6 +2262,8 @@ void Print::process(long long *time_cost_with_cache, bool use_cache)
obj->set_done(posInfill);
if (obj->set_started(posIroning))
obj->set_done(posIroning);
if (obj->set_started(posContouring))
obj->set_done(posContouring);
if (obj->set_started(posSupportMaterial))
obj->set_done(posSupportMaterial);
if (obj->set_started(posDetectOverhangsForLift))
@@ -2630,7 +2643,7 @@ void Print::_make_skirt()
flow.width(),
(float)initial_layer_print_height // this will be overridden at G-code export time
)));
eloop.paths.back().polyline = loop.split_at_first_point();
eloop.paths.back().polyline = Polyline3(loop.split_at_first_point());
m_skirt.append(eloop);
if (m_config.min_skirt_length.value > 0) {
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
@@ -2688,7 +2701,7 @@ void Print::_make_skirt()
flow.width(),
(float)initial_layer_print_height // this will be overridden at G-code export time
)));
eloop.paths.back().polyline = loop.split_at_first_point();
eloop.paths.back().polyline = Polyline3(loop.split_at_first_point());
object->m_skirt.append(std::move(eloop));
if (m_config.min_skirt_length.value > 0) {
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
@@ -4093,7 +4106,8 @@ static void from_json(const json& j, Polyline& poly_line) {
}
static void from_json(const json& j, ExtrusionPath& extrusion_path) {
extrusion_path.polyline = j[JSON_EXTRUSION_POLYLINE];
Polyline temp_polyline = j[JSON_EXTRUSION_POLYLINE];
extrusion_path.polyline = Polyline3(temp_polyline);
extrusion_path.mm3_per_mm = j[JSON_EXTRUSION_MM3_PER_MM];
extrusion_path.width = j[JSON_EXTRUSION_WIDTH];
extrusion_path.height = j[JSON_EXTRUSION_HEIGHT];
@@ -4946,8 +4960,9 @@ ExtrusionLayers FakeWipeTower::getTrueExtrusionLayersFromWipeTower() const
paths.reserve(it->second.size());
for (auto &polyline : it->second) {
ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, layer_heights[index]);
path.polyline = polyline;
for (auto &p : path.polyline.points) p += trans;
path.polyline = Polyline3(polyline);
Point3 trans3(trans, 0);
for (auto &p : path.polyline.points) p += trans3;
paths.push_back(path);
}
el.paths = std::move(paths);

View File

@@ -92,7 +92,7 @@ enum PrintStep {
enum PrintObjectStep {
posSlice, posPerimeters,posEstimateCurledExtrusions, posPrepareInfill,
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
posInfill, posIroning, posContouring, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
// BBS
posDetectOverhangsForLift,
posSimplifyWall, posSimplifyInfill,
@@ -496,6 +496,8 @@ private:
void prepare_infill();
void infill();
void ironing();
bool need_z_contouring() const;
void contour_z();
void generate_support_material();
void estimate_curled_extrusions();
void simplify_extrusion_path();
@@ -642,14 +644,14 @@ struct FakeWipeTower
std::vector<ExtrusionPaths> paths;
for (float h = 0.f; h < height; h += layer_height) {
ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, layer_height);
path.polyline = {minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner};
path.polyline = Polyline3(Polyline{{minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner}});
paths.push_back({path});
if (h == 0.f) { // add brim
ExtrusionPath fakeBrim(ExtrusionRole::erBrim, 0.0, 0.0, layer_height);
Point wtbminCorner = {minCorner - Point{bd, bd}};
Point wtbmaxCorner = {maxCorner + Point{bd, bd}};
fakeBrim.polyline = {wtbminCorner, {wtbmaxCorner.x(), wtbminCorner.y()}, wtbmaxCorner, {wtbminCorner.x(), wtbmaxCorner.y()}, wtbminCorner};
fakeBrim.polyline = Polyline3(Polyline{{wtbminCorner, {wtbmaxCorner.x(), wtbminCorner.y()}, wtbmaxCorner, {wtbminCorner.x(), wtbmaxCorner.y()}, wtbminCorner}});
paths.back().push_back(fakeBrim);
}
}
@@ -686,13 +688,13 @@ struct FakeWipeTower
ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, lh);
path.polyline = { minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner };
path.polyline = Polyline3(Polyline{{ minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner }});
paths.push_back({ path });
// We added the border, now add several parallel lines so we can detect an object that is fully inside the tower.
// For now, simply use fixed spacing of 3mm.
for (coord_t y=minCorner.y()+scale_(3.); y<maxCorner.y(); y+=scale_(3.)) {
path.polyline = { {minCorner.x(), y}, {maxCorner.x(), y} };
path.polyline = Polyline3(Polyline{{ {minCorner.x(), y}, {maxCorner.x(), y} }});
paths.back().emplace_back(path);
}

View File

@@ -696,11 +696,11 @@ void PrintConfigDef::init_common_params()
def->set_default_value(new ConfigOptionInt(1));
def = this->add("elefant_foot_layers_density", coPercent);
def->label = L("Elefant foot layers density");
def->label = L("Elephant foot layers density");
def->category = L("Quality");
def->tooltip = L("Density of internal solid infill for elefant foot layers compensation. "
"The initial value for the second layer is set. "
"Subsequent layers become linearly denser by the height specified in elefant_foot_compensation_layers. ");
def->tooltip = L("Density of internal solid infill for Elephant foot layers compensation.\n"
"The initial value for the second layer is set.\n"
"Subsequent layers become linearly denser by the height specified in elefant_foot_compensation_layers.");
def->sidetext = "%";
def->min = 50;
def->max = 100;
@@ -2191,6 +2191,7 @@ void PrintConfigDef::init_fff_params()
"This setting changes all extrusion flow of this filament in G-code proportionally. "
"The recommended value range is between 0.95 and 1.05. "
"You may be able to tune this value to get a nice flat surface if there is slight overflow or underflow.");
def->min = 0;
def->max = 2;
def->mode = comAdvanced;
def->nullable = true;
@@ -4111,6 +4112,53 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("ironing_expansion", coFloat);
def->label = L("Ironing expansion");
def->category = L("Quality");
def->tooltip = L("Expand or contract the ironing area.");
def->sidetext = L("mm");
def->min = -100;
def->max = 100;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("zaa_enabled", coBool);
def->label = L("Z contouring enabled");
def->category = L("Quality");
def->tooltip = L("Enable Z-layer contouring (aka Z-layer anti-aliasing).");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("zaa_minimize_perimeter_height", coFloat);
def->label = L("Minimize wall height angle");
def->category = L("Quality");
def->tooltip = L("Reduce the height of top-surface perimeters to match the model edge height.\n"
"Affects perimeters with a slope less than this angle (degrees).\n"
"A reasonable value is 35. Set to 0 to disable.");
def->sidetext = L("°");
def->min = 0;
def->max = 90;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("zaa_dont_alternate_fill_direction", coBool);
def->label = L("Don't alternate fill direction");
def->category = L("Quality");
def->tooltip = L("Disable alternating fill direction when using Z contouring.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("zaa_min_z", coFloat);
def->label = L("Minimum z height");
def->category = L("Quality");
def->tooltip = L("Minimum Z-layer height.\n"
"Also controls the slicing plane.");
def->sidetext = L("mm");
def->min = 0;
def->max = 100;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.05));
def = this->add("layer_change_gcode", coString);
def->label = L("Layer change G-code");
def->tooltip = L("This G-code is inserted at every layer change after the Z lift.");
@@ -5192,7 +5240,8 @@ void PrintConfigDef::init_fff_params()
def->label = L("Scarf joint flow ratio");
def->category = L("Quality");
def->tooltip = L("This factor affects the amount of material for scarf joints.");
def->mode = comDevelop;
def->mode = comExpert;
def->min = 0;
def->max = 2;
def->set_default_value(new ConfigOptionFloat(1));

View File

@@ -1198,7 +1198,13 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatOrPercent, scarf_joint_speed))
((ConfigOptionFloat, scarf_joint_flow_ratio))
((ConfigOptionPercent, scarf_overhang_threshold))
)
// Orca: Z Anti-Aliasing (aka Z Contouring)
((ConfigOptionBool, zaa_enabled))
((ConfigOptionBool, zaa_dont_alternate_fill_direction))
((ConfigOptionFloat, zaa_min_z))
((ConfigOptionFloat, zaa_minimize_perimeter_height))
)
PRINT_CONFIG_CLASS_DEFINE(
MachineEnvelopeConfig,

View File

@@ -1,4 +1,6 @@
#include "Exception.hpp"
#include "Model.hpp"
#include "Point.hpp"
#include "Print.hpp"
#include "BoundingBox.hpp"
#include "ClipperUtils.hpp"
@@ -8,6 +10,7 @@
#include "Layer.hpp"
#include "MutablePolygon.hpp"
#include "PrintConfig.hpp"
#include "SLA/IndexedMesh.hpp"
#include "Support/SupportMaterial.hpp"
#include "Support/SupportSpotsGenerator.hpp"
#include "Support/TreeSupport.hpp"
@@ -22,7 +25,11 @@
#include "format.hpp"
#include "AABBTreeLines.hpp"
#include <cstddef>
#include <float.h>
#include <iterator>
#include <mutex>
#include <string>
#include <oneapi/tbb/blocked_range.h>
#include <oneapi/tbb/concurrent_vector.h>
#include <oneapi/tbb/parallel_for.h>
@@ -709,6 +716,65 @@ void PrintObject::ironing()
}
}
bool PrintObject::need_z_contouring() const
{
size_t num_regions = this->num_printing_regions();
for (size_t region_id = 0; region_id < num_regions; region_id++) {
if (this->printing_region(region_id).config().zaa_enabled)
return true;
}
return false;
}
void PrintObject::contour_z()
{
if (!this->set_started(posContouring)) {
return;
}
m_print->set_status(40, L("Z contouring"));
BOOST_LOG_TRIVIAL(debug) << "Contouring in parallel - start";
TriangleMesh mesh = this->m_model_object->raw_mesh();
if (m_model_object->instances.size() != 1) {
throw RuntimeError("ContourZ: unexpected number of instances");
}
ModelInstance *inst = m_model_object->instances.front();
Point center_offset = this->center_offset();
Geometry::Transformation trans = inst->get_transformation();
double z = this->m_model_object->min_z();
trans.set_offset(Vec3d(-unscale<double>(center_offset.x()), -unscale<double>(center_offset.y()), 0));
mesh.transform(trans.get_matrix());
sla::IndexedMesh imesh(mesh);
imesh.ground_level_offset(-z);
std::mutex mtx;
size_t completed = 0;
tbb::parallel_for(
// Contouring starting with layer second layer to avoid build plate collision
tbb::blocked_range<size_t>(1, m_layers.size()),
[&, this](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); layer_idx++) {
m_print->throw_if_canceled();
m_layers[layer_idx]->make_contour_z(imesh);
std::scoped_lock lock(mtx);
completed++;
std::string msg = (boost::format("Z contoured layer %d/%d (%d%%)") % (completed) % m_layers.size() % int(double(completed) / m_layers.size() * 100)).str();
m_print->set_status(40, msg);
}
}
);
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Contouring in parallel - end";
this->set_done(posContouring);
}
// BBS
void PrintObject::clear_overhangs_for_lift()
{
@@ -1370,15 +1436,15 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// propagate to dependent steps
if (step == posPerimeters) {
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posContouring, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posPrepareInfill) {
invalidated |= this->invalidate_steps({ posInfill, posIroning, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posInfill, posIroning, posContouring, posSimplifyPath, posSimplifyInfill });
} else if (step == posInfill) {
invalidated |= this->invalidate_steps({ posIroning, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posIroning, posContouring, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posSlice) {
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifyInfill });
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posContouring, posSupportMaterial, posSimplifyPath, posSimplifyInfill });
invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false;
} else if (step == posSupportMaterial) {

View File

@@ -4,6 +4,7 @@
#include "ClipperUtils.hpp"
#include "ElephantFootCompensation.hpp"
#include "Exception.hpp"
#include "I18N.hpp"
#include "Layer.hpp"
#include "MultiMaterialSegmentation.hpp"
@@ -34,6 +35,23 @@ LayerPtrs new_layers(
coordf_t lo = object_layers[i_layer];
coordf_t hi = object_layers[i_layer + 1];
coordf_t slice_z = 0.5 * (lo + hi);
bool zaa_active = false;
coordf_t z_offset = 0.0;
size_t num_regions = print_object->num_printing_regions();
for (size_t rid = 0; rid < num_regions; ++rid) {
const auto &rcfg = print_object->printing_region(rid).config();
if (rcfg.zaa_enabled) {
if (!zaa_active || rcfg.zaa_min_z < z_offset)
z_offset = rcfg.zaa_min_z;
zaa_active = true;
}
}
if (zaa_active) {
slice_z = lo + z_offset;
if ((slice_z < lo && !is_approx(slice_z, lo)) || (slice_z > hi && !is_approx(slice_z, hi))) {
throw RuntimeError("Bad min Z value");
}
}
Layer *layer = new Layer(id ++, print_object, hi - lo, hi + zmin, slice_z);
out.emplace_back(layer);
if (prev != nullptr) {

View File

@@ -1000,7 +1000,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy2(SegmentEndPointFunc
std::vector<std::pair<size_t, bool>> chain_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near)
{
auto segment_end_point = [&entities](size_t idx, bool first_point) -> const Point& { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); };
auto segment_end_point = [&entities](size_t idx, bool first_point) -> Point { return first_point ? entities[idx]->first_point() : entities[idx]->last_point(); };
auto could_reverse = [&entities](size_t idx) { const ExtrusionEntity *ee = entities[idx]; return ee->is_loop() || ee->can_reverse(); };
std::vector<std::pair<size_t, bool>> out = chain_segments_greedy_constrained_reversals<Point, decltype(segment_end_point), decltype(could_reverse)>(segment_end_point, could_reverse, entities.size(), start_near);
for (std::pair<size_t, bool> &segment : out) {
@@ -1028,6 +1028,11 @@ void reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const s
entities.swap(out);
}
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point &start_near)
{
chain_and_reorder_extrusion_entities(entities, &start_near);
}
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near)
{
// this function crashes if there are empty elements in entities
@@ -1038,7 +1043,7 @@ void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entitie
std::vector<std::pair<size_t, bool>> chain_extrusion_paths(std::vector<ExtrusionPath> &extrusion_paths, const Point *start_near)
{
auto segment_end_point = [&extrusion_paths](size_t idx, bool first_point) -> const Point& { return first_point ? extrusion_paths[idx].first_point() : extrusion_paths[idx].last_point(); };
auto segment_end_point = [&extrusion_paths](size_t idx, bool first_point) -> Point { return first_point ? extrusion_paths[idx].first_point() : extrusion_paths[idx].last_point(); };
return chain_segments_greedy<Point, decltype(segment_end_point)>(segment_end_point, extrusion_paths.size(), start_near);
}

View File

@@ -20,6 +20,7 @@ std::vector<size_t> chain_expolygons(const ExPolygons &input_exploy);
std::vector<std::pair<size_t, bool>> chain_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near = nullptr);
void reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const std::vector<std::pair<size_t, bool>> &chain);
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point &start_near);
void chain_and_reorder_extrusion_entities(std::vector<ExtrusionEntity*> &entities, const Point *start_near = nullptr);
std::vector<std::pair<size_t, bool>> chain_extrusion_paths(std::vector<ExtrusionPath> &extrusion_paths, const Point *start_near = nullptr);

View File

@@ -1163,7 +1163,7 @@ static void modulate_extrusion_by_overlapping_layers(
for (ExtrusionEntity *ee : extrusions_in_out) {
ExtrusionPath *path = dynamic_cast<ExtrusionPath*>(ee);
assert(path != nullptr);
polylines.emplace_back(Polyline(std::move(path->polyline)));
polylines.emplace_back(path->polyline.to_polyline());
path_ends.emplace_back(std::pair<Point, Point>(polylines.back().points.front(), polylines.back().points.back()));
delete path;
}
@@ -1288,9 +1288,10 @@ static void modulate_extrusion_by_overlapping_layers(
if (! path->polyline.points.empty())
path->polyline.points.pop_back();
// Consume the fragment's polyline, remove it from the input fragments, so it will be ignored the next time.
path->polyline.append(std::move(frag_polyline));
path->polyline.append(Polyline3(std::move(frag_polyline)));
frag_polyline.points.clear();
pt_current = path->polyline.points.back();
const Point3 &pt_back3 = path->polyline.points.back();
pt_current = Point(pt_back3.x(), pt_back3.y());
if (pt_current == pt_end) {
// End of the path.
break;

View File

@@ -1181,7 +1181,9 @@ namespace SupportMaterialInternal {
// This is a complete loop.
// Add the outer contour first.
Polygon poly;
poly.points = ep.polyline.points;
// Convert Points3 to Points
for (const Point3 &p3 : ep.polyline.points)
poly.points.emplace_back(p3.x(), p3.y());
poly.points.pop_back();
if (poly.area() < 0)
poly.reverse();

Some files were not shown because too many files have changed in this diff Show More