diff --git a/.github/workflows/conan-package.yml b/.github/workflows/conan-package.yml
new file mode 100644
index 0000000000..0a625d2b0a
--- /dev/null
+++ b/.github/workflows/conan-package.yml
@@ -0,0 +1,128 @@
+---
+name: conan-package
+
+# Exports the recipe, sources and binaries for Mac, Windows and Linux and upload these to the server such that these can
+# be used downstream.
+#
+# It should run on pushes against main or CURA-* branches, but it will only create the binaries for main and release branches
+
+on:
+ workflow_dispatch:
+ inputs:
+ create_binaries_windows:
+ required: true
+ default: false
+ description: 'create binaries Windows'
+ create_binaries_linux:
+ required: true
+ default: false
+ description: 'create binaries Linux'
+ create_binaries_macos:
+ required: true
+ default: false
+ description: 'create binaries Macos'
+
+ push:
+ paths:
+ - 'src/**'
+ - 'cmake/**'
+ - 'tests/**'
+ - 'conanfile.py'
+ - 'conandata.yml'
+ - 'CMakeLists.txt'
+ - '.github/workflows/conan-package.yml'
+ - '.github/worflows/requirements-conan-package.txt'
+ branches:
+ - main
+ - 'CURA-*'
+ - '[1-9]+.[0-9]+'
+ tags:
+ - '[0-9]+.[0-9]+.[0-9]+'
+
+jobs:
+ conan-recipe-version:
+ uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@main
+ with:
+ project_name: curaengine
+
+ conan-package-export:
+ needs: [ conan-recipe-version ]
+ uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@main
+ with:
+ recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
+ recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }}
+ recipe_id_pr: ${{ needs.conan-recipe-version.outputs.recipe_id_pr }}
+ runs_on: 'ubuntu-20.04'
+ python_version: '3.10.4'
+ conan_config_branch: 'master'
+ conan_logging_level: 'info'
+ secrets: inherit
+
+ conan-package-create-macos:
+ # FIXME: For release branches: maybe rename the branch to release/**
+ if: ${{ (github.event_name == 'push' && github.ref_name == 'main') || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_macos) }}
+ needs: [ conan-recipe-version, conan-package-export ]
+
+ uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
+ with:
+ recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
+ runs_on: 'macos-10.15'
+ python_version: '3.10.4'
+ conan_config_branch: 'master'
+ conan_logging_level: 'info'
+ secrets: inherit
+
+ conan-package-create-windows:
+ # FIXME: For release branches: maybe rename the branch to release/**
+ if: ${{ (github.event_name == 'push' && github.ref_name == 'main') || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_windows) }}
+ needs: [ conan-recipe-version, conan-package-export ]
+
+ uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
+ with:
+ recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
+ runs_on: 'windows-2022'
+ python_version: '3.10.4'
+ conan_config_branch: 'master'
+ conan_logging_level: 'info'
+ secrets: inherit
+
+ conan-package-create-linux:
+ # FIXME: For release branches: maybe rename the branch to release/**
+ if: ${{ (github.event_name == 'push' && github.ref_name == 'main') || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux) }}
+ needs: [ conan-recipe-version, conan-package-export ]
+
+ uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
+ with:
+ recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
+ runs_on: 'ubuntu-20.04'
+ python_version: '3.10.4'
+ conan_config_branch: 'master'
+ conan_logging_level: 'info'
+ secrets: inherit
+
+ notify-export:
+ if: ${{ always() }}
+ needs: [ conan-package-export ]
+
+ uses: ultimaker/cura/.github/workflows/notify.yml@main
+ with:
+ success: ${{ contains(join(needs.*.result, ','), 'success') }}
+ success_title: "New Conan recipe exported in ${{ github.repository }}"
+ success_body: "Exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+ failure_title: "Failed to export Conan Export in ${{ github.repository }}"
+ failure_body: "Failed to exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+ secrets: inherit
+
+ notify-create:
+ # FIXME: For release branches: maybe rename the branch to release/**
+ if: ${{ always() && ((github.event_name == 'push' && github.ref_name == 'main') || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux)) }}
+ needs: [ conan-package-create-macos, conan-package-create-windows, conan-package-create-linux ]
+
+ uses: ultimaker/cura/.github/workflows/notify.yml@main
+ with:
+ success: ${{ contains(join(needs.*.result, ','), 'success') }}
+ success_title: "New binaries created in ${{ github.repository }}"
+ success_body: "Created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+ failure_title: "Failed to create binaries in ${{ github.repository }}"
+ failure_body: "Failed to created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+ secrets: inherit
diff --git a/.github/workflows/requirements-conan-package.txt b/.github/workflows/requirements-conan-package.txt
new file mode 100644
index 0000000000..49f3f7bb9d
--- /dev/null
+++ b/.github/workflows/requirements-conan-package.txt
@@ -0,0 +1,3 @@
+conan
+gitpython
+sip==6.5.1
\ No newline at end of file
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index 5a7a781bab..dd104df331 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -1,5 +1,6 @@
---
name: unit-test
+# FIXME: This should be a reusable workflow
on:
push:
@@ -8,74 +9,110 @@ on:
- 'cmake/**'
- 'tests/**'
- 'conanfile.py'
+ - 'conandata.yml'
- 'CMakeLists.txt'
- '.github/workflows/unit-test.yml'
+ - '.github/worflows/requirements-conan-package.txt'
branches:
- main
- 'CURA-*'
- - 'CT_fix'
+ - '[0-9]+.[0-9]+'
tags:
- - '[5-9].[0-9].+*'
+ - '[0-9]+.[0-9]+.[0-9]+'
pull_request:
paths:
- 'src/**'
- 'cmake/**'
- 'tests/**'
- 'conanfile.py'
+ - 'conandata.yml'
- 'CMakeLists.txt'
- '.github/workflows/unit-test.yml'
+ - '.github/worflows/requirements-conan-package.txt'
branches:
- main
- - '[5-9].[0-9]'
+ - 'CURA-*'
+ - '[0-9]+.[0-9]+'
+ tags:
+ - '[0-9]+.[0-9]+.[0-9]+'
env:
- CONAN_USER: ${{ secrets.CONAN_USER }}
- CONAN_PASS: ${{ secrets.CONAN_PASS }}
+ CONAN_LOGIN_USERNAME_CURA: ${{ secrets.CONAN_USER }}
+ CONAN_PASSWORD_CURA: ${{ secrets.CONAN_PASS }}
+ CONAN_LOGIN_USERNAME_CURA_CE: ${{ secrets.CONAN_USER }}
+ CONAN_PASSWORD_CURA_CE: ${{ secrets.CONAN_PASS }}
+ CONAN_LOG_RUN_TO_OUTPUT: 1
+ CONAN_LOGGING_LEVEL: info
+ CONAN_NON_INTERACTIVE: 1
jobs:
+ conan-recipe-version:
+ uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@main
+ with:
+ project_name: curaengine
+
testing:
runs-on: ubuntu-20.04
+ needs: [ conan-recipe-version ]
steps:
- name: Checkout CuraEngine
uses: actions/checkout@v3
- name: Setup Python and pip
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v4
with:
- python-version: '3.10.4'
+ python-version: '3.10.x'
architecture: 'x64'
cache: 'pip'
+ cache-dependency-path: .github/workflows/requirements-conan-package.txt
- - name: Prepare Conan and sip-build (Bash)
- if: ${{ runner.os != 'Windows' }}
+ - name: Install Python requirements and Create default Conan profile
run: |
- pip install --require-hashes -r requirements.txt
- # FIXME: Once we fully support Conan change to: `conan config install https://github.com/Ultimaker/conan-config.git`
- conan config install https://github.com/Ultimaker/conan-config.git -a "-b CURA-9177_Fix_CI_CD" -tf $HOME/.conan
+ pip install -r requirements-conan-package.txt
conan profile new default --detect
- conan user -p $CONAN_PASS -r ultimaker $CONAN_USER
+ working-directory: .github/workflows/
+
+ - name: Use Conan download cache (Bash)
+ if: ${{ runner.os != 'Windows' }}
+ run: conan config set storage.download_cache="$HOME/.conan/conan_download_cache"
- name: Cache Conan local repository packages (Bash)
uses: actions/cache@v3
+ if: ${{ runner.os != 'Windows' }}
with:
path: |
$HOME/.conan/data
- key: ${{ runner.os }}-testing
+ $HOME/.conan/conan_download_cache
+ key: conan-${{ runner.os }}-${{ runner.arch }}
+
+ - name: Install Linux system requirements
+ if: ${{ runner.os == 'Linux' }}
+ run: sudo apt install build-essential checkinstall zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev -y
+
+ - name: Get Conan configuration
+ run: conan config install https://github.com/Ultimaker/conan-config.git
- name: Install dependencies
- run: conan install . -o enable_testing=True -pr:b cura_build.jinja -pr:h cura_release.jinja --build=missing --update -g VirtualBuildEnv
+ run: conan install . ${{ needs.conan-recipe-version.outputs.recipe_id_full }} -o enable_testing=True -s build_type=Release --build=missing --update -g GitHubActionsRunEnv -g GitHubActionsBuildEnv
- name: Upload the Dependency package(s)
- run: conan upload "*" -r ultimaker --all -c
+ run: conan upload "*" -r cura --all -c
+
+ - name: Set Environment variables from Conan install (bash)
+ if: ${{ runner.os != 'Windows' }}
+ run: |
+ . ./activate_github_actions_runenv.sh
+ . ./activate_github_actions_buildenv.sh
+ working-directory: cmake-build-release/conan
- name: Run Unit Test CuraEngine
id: run-test
run: |
- cmake --toolchain cmake-build-release/conan/conan_toolchain.cmake -S . -B cmake-build-release/
- cmake --build cmake-build-release/
- cd cmake-build-release/
+ cmake --toolchain ./conan/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -S .. -B .
+ cmake --build .
ctest --output-junit engine_test.xml
+ working-directory: cmake-build-release
- name: Publish Unit Test Results
id: test-results
@@ -86,4 +123,4 @@ jobs:
**/*.xml
- name: Conclusion
- run: echo "Conclusion is ${{ fromJSON( steps.test-results.outputs.json ).conclusion }}"
\ No newline at end of file
+ run: echo "Conclusion is ${{ fromJSON( steps.test-results.outputs.json ).conclusion }}"
diff --git a/.gitignore b/.gitignore
index 7b789a2f75..eeddac5803 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,8 +17,8 @@ callgrind/*
build/*
debug_build/*
release_build/*
-cmake-build-debug/*
-cmake-build-release/*
+cmake-build-*
+cmake-build-*
libs/stb
*.pyc
*.exe
@@ -64,3 +64,6 @@ documentation/latex/*
## Test results.
tests/output.xml
callgrind.out.*
+
+CMakeUserPresets.json
+/conan_imports_manifest.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e979a058a3..f3a427af98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,8 +24,7 @@ if (ENABLE_ARCUS)
message(STATUS "Building with Arcus")
find_package(arcus 5.0.0 REQUIRED)
- find_package(protobuf_BUILD 3.17.1 REQUIRED) # Used for protoc
- find_package(protobuf 3.17.1 REQUIRED) # Used for linking
+ find_package(protobuf 3.17.1 REQUIRED)
protobuf_generate_cpp(engine_PB_SRCS engine_PB_HEADERS Cura.proto)
endif ()
diff --git a/README.md b/README.md
index eb198e3a4b..ce217952ae 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,8 @@
+
+
diff --git a/clang-format b/clang-format
deleted file mode 100644
index e3c247c51d..0000000000
--- a/clang-format
+++ /dev/null
@@ -1,35 +0,0 @@
----
-AllowAllParametersOfDeclarationOnNextLine: 'true'
-AllowShortBlocksOnASingleLine: 'true'
-AllowShortFunctionsOnASingleLine: None
-AllowShortIfStatementsOnASingleLine: 'false'
-AllowShortLoopsOnASingleLine: 'false'
-AlwaysBreakTemplateDeclarations: 'true'
-BreakBeforeBinaryOperators: 'true'
-BreakBeforeBraces: Allman
-BreakConstructorInitializersBeforeComma: 'true'
-ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
-Cpp11BracedListStyle: 'false'
-DerivePointerAlignment: 'false'
-IndentCaseLabels: 'true'
-IndentWidth: '4'
-KeepEmptyLinesAtTheStartOfBlocks: 'false'
-Language: Cpp
-MaxEmptyLinesToKeep: '2'
-NamespaceIndentation: None
-ObjCSpaceAfterProperty: 'true'
-ObjCSpaceBeforeProtocolList: 'false'
-PointerAlignment: Left
-SpaceBeforeAssignmentOperators: 'true'
-SpaceBeforeParens: ControlStatements
-SpaceInEmptyParentheses: 'false'
-SpacesBeforeTrailingComments: '1'
-SpacesInAngles: 'false'
-SpacesInCStyleCastParentheses: 'false'
-SpacesInContainerLiterals: 'true'
-SpacesInParentheses: 'false'
-Standard: Cpp11
-TabWidth: '5'
-UseTab: Never
-
-...
diff --git a/conandata.yml b/conandata.yml
new file mode 100644
index 0000000000..8d1546b888
--- /dev/null
+++ b/conandata.yml
@@ -0,0 +1,56 @@
+"None":
+ requirements:
+ - "clipper/6.4.2"
+ - "boost/1.78.0"
+ - "rapidjson/1.1.0"
+ - "stb/20200203"
+ requirements_arcus:
+ - "protobuf/3.17.1"
+ - "arcus/(latest)@ultimaker/stable"
+ - "zlib/1.2.12"
+ build_requirements_arcus:
+ - "protobuf/3.17.1"
+ build_requirements_testing:
+ - "gtest/[>=1.10.0]"
+"5.1.0":
+ requirements:
+ - "clipper/6.4.2"
+ - "boost/1.78.0"
+ - "rapidjson/1.1.0"
+ - "stb/20200203"
+ requirements_arcus:
+ - "protobuf/3.17.1"
+ - "arcus/5.1.0"
+ - "zlib/1.2.12"
+ build_requirements_arcus:
+ - "protobuf/3.17.1"
+ build_requirements_testing:
+ - "gtest/[>=1.10.0]"
+"5.1.0-beta":
+ requirements:
+ - "clipper/6.4.2"
+ - "boost/1.78.0"
+ - "rapidjson/1.1.0"
+ - "stb/20200203"
+ requirements_arcus:
+ - "protobuf/3.17.1"
+ - "arcus/(latest)@ultimaker/stable"
+ - "zlib/1.2.12"
+ build_requirements_arcus:
+ - "protobuf/3.17.1"
+ build_requirements_testing:
+ - "gtest/[>=1.10.0]"
+"5.1.0-alpha":
+ requirements:
+ - "clipper/6.4.2"
+ - "boost/1.78.0"
+ - "rapidjson/1.1.0"
+ - "stb/20200203"
+ requirements_arcus:
+ - "protobuf/3.17.1"
+ - "arcus/(latest)@ultimaker/cura_9365"
+ - "zlib/1.2.12"
+ build_requirements_arcus:
+ - "protobuf/3.17.1"
+ build_requirements_testing:
+ - "gtest/[>=1.10.0]"
\ No newline at end of file
diff --git a/conanfile.py b/conanfile.py
index 2dcdd53ece..4b067ede23 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -20,6 +20,10 @@ class CuraEngineConan(ConanFile):
build_policy = "missing"
exports = "LICENSE*"
settings = "os", "compiler", "build_type", "arch"
+
+ python_requires = "umbase/0.1.1@ultimaker/testing"
+ python_requires_extend = "umbase.UMBaseConanfile"
+
options = {
"enable_arcus": [True, False],
"enable_openmp": [True, False],
@@ -37,13 +41,24 @@ class CuraEngineConan(ConanFile):
"revision": "auto"
}
+ _cmake = None
+
+ @property
+ def cmake(self):
+ if self._cmake is None:
+ self._cmake = CMake(self)
+ return self._cmake
+
def config_options(self):
if self.settings.os == "Macos":
self.options.enable_openmp = False
def configure(self):
self.options["boost"].header_only = True
- self.options["*"].shared = True
+ self.options["clipper"].shared = True
+ if self.options.enable_arcus:
+ self.options["arcus"].shared = True
+ self.options["protobuf"].shared = True
def validate(self):
if self.settings.compiler.get_safe("cppstd"):
@@ -53,44 +68,28 @@ def validate(self):
raise ConanInvalidConfiguration("Only versions 5+ are support")
def build_requirements(self):
- self.tool_requires("ninja/[>=1.10.0]")
- self.tool_requires("cmake/[>=3.23.0]")
if self.options.enable_arcus:
- self.tool_requires("protobuf/3.17.1")
+ for req in self._um_data(self.version)["build_requirements_arcus"]:
+ self.tool_requires(req)
if self.options.enable_testing:
- self.test_requires("gtest/[>=1.10.0]")
+ for req in self._um_data(self.version)["build_requirements_testing"]:
+ self.test_requires(req)
def requirements(self):
- self.requires("protobuf/3.17.1")
- self.requires("clipper/6.4.2")
- self.requires("boost/1.78.0")
- self.requires("rapidjson/1.1.0")
- self.requires("stb/20200203")
+ for req in self._um_data(self.version)["requirements"]:
+ self.requires(req)
if self.options.enable_arcus:
- self.requires("protobuf/3.17.1")
- self.requires("arcus/5.0.1-PullRequest0137.86@ultimaker/testing")
+ for req in self._um_data(self.version)["requirements_arcus"]:
+ self.requires(req)
def generate(self):
cmake = CMakeDeps(self)
- if self.options.enable_arcus:
- if len(cmake.build_context_activated) == 0:
- cmake.build_context_activated = ["protobuf"]
- else:
- cmake.build_context_activated.append("protobuf")
- cmake.build_context_suffix = {"protobuf": "_BUILD"}
- if len(cmake.build_context_activated) == 0:
- cmake.build_context_build_modules = ["protobuf"]
- else:
- cmake.build_context_build_modules.append("protobuf")
if self.options.enable_testing:
- if len(cmake.build_context_build_modules) == 0:
- cmake.build_context_activated = ["gtest"]
- else:
- cmake.build_context_activated.append("gtest")
+ cmake.build_context_activated = ["gtest"]
cmake.generate()
- tc = CMakeToolchain(self, generator = "Ninja")
+ tc = CMakeToolchain(self)
tc.variables["ENABLE_ARCUS"] = self.options.enable_arcus
tc.variables["BUILD_TESTING"] = self.options.enable_testing
@@ -105,6 +104,10 @@ def generate(self):
tc.generate()
def layout(self):
+ # TODO: Use the cmake_layout provided by Conan, that requires restructuring the headers and sources,
+ # or if we decided against a cmake_layout, we should at least make things uniform across our projects
+ # and create the layout by defining a function in the UMBaseConanfile.
+ # https://docs.conan.io/en/latest/reference/conanfile/tools/layout.html
self.folders.source = "."
try:
build_type = str(self.settings.build_type)
@@ -126,21 +129,25 @@ def layout(self):
self.cpp.package.bindirs = ['bin']
def imports(self):
- if self.settings.os == "Windows":
- self.copy("*", dst=self.build_folder, src="@bindirs")
- self.copy("*", dst=self.build_folder, src="@libdirs")
- if self.options.enable_testing:
- dest = os.path.join(self.build_folder, "tests")
- self.copy("*", dst=dest, src="@bindirs")
- self.copy("*", dst=dest, src="@libdirs")
+ self.copy("*.dll", dst=self.build_folder, src="@bindirs")
+ self.copy("*.dylib", dst=self.build_folder, src="@bindirs")
+ if self.options.enable_testing:
+ dest = os.path.join(self.build_folder, "tests")
+ self.copy("*.dll", dst=dest, src="@bindirs")
+ self.copy("*.dylib", dst=dest, src="@bindirs")
def build(self):
- cmake = CMake(self)
+ cmake = self.cmake
cmake.configure()
cmake.build()
- if self.options.enable_testing:
- cmake.test()
+
+ def test(self):
+ if not tools.cross_building(self) and self.options.enable_testing:
+ self.cmake.test()
def package(self):
packager = files.AutoPackager(self)
- packager.run()
\ No newline at end of file
+ packager.patterns.bin = ["CuraEngine.exe", "CuraEngine"]
+ packager.run()
+ self.copy("CuraEngine", src = self.build_folder, dst = "bin")
+ self.copy("CuraEngine.exe", src = self.build_folder, dst = "bin")
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 59ebda4b26..0000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,152 +0,0 @@
-### Conan ###
-
-conan==1.47.0 \
- --hash=sha256:c0f066be1871ae23a9dbe7465929ae38f221531b7025f85cdd56d4790c1816be
-colorama==0.4.4 \
- --hash=sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b \
- --hash=sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2
-urllib3==1.26.9 \
- --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e \
- --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14
-six==1.16.0 \
- --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
- --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
-distro==1.6.0 \
- --hash=sha256:83f5e5a09f9c5f68f60173de572930effbcc0287bb84fdc4426cb4168c088424 \
- --hash=sha256:c8713330ab31a034623a9515663ed87696700b55f04556b97c39cd261aa70dc7
-requests==2.27.1 \
- --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \
- --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d
-charset-normalizer==2.0.10 \
- --hash=sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd \
- --hash=sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455
-certifi==2021.10.8 \
- --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \
- --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569
-PyYAML==5.4.1 \
- --hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \
- --hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \
- --hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \
- --hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \
- --hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \
- --hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \
- --hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \
- --hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \
- --hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \
- --hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \
- --hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e \
- --hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \
- --hash=sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347 \
- --hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \
- --hash=sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541 \
- --hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \
- --hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \
- --hash=sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc \
- --hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \
- --hash=sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa \
- --hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \
- --hash=sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122 \
- --hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \
- --hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \
- --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \
- --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \
- --hash=sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247 \
- --hash=sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6 \
- --hash=sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0
-Pygments==2.11.2 \
- --hash=sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65 \
- --hash=sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a
-bottle==0.12.19 \
- --hash=sha256:a9d73ffcbc6a1345ca2d7949638db46349f5b2b77dac65d6494d45c23628da2c \
- --hash=sha256:f6b8a34fe9aa406f9813c02990db72ca69ce6a158b5b156d2c41f345016a723d
-node-semver==0.6.1 \
- --hash=sha256:4016f7c1071b0493f18db69ea02d3763e98a633606d7c7beca811e53b5ac66b7 \
- --hash=sha256:d4bf83873894591a0cbb6591910d96917fbadc9731e8e39e782d3a2fbc2b841e
-Jinja2==3.0.3 \
- --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \
- --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7
-python-dateutil==2.8.2 \
- --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
- --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
-patch-ng==1.17.4 \
- --hash=sha256:627abc5bd723c8b481e96849b9734b10065426224d4d22cd44137004ac0d4ace
-tqdm==4.63.0 \
- --hash=sha256:1d9835ede8e394bb8c9dcbffbca02d717217113adc679236873eeaac5bc0b3cd \
- --hash=sha256:e643e071046f17139dea55b880dc9b33822ce21613b4a4f5ea57f202833dbc29
-PyJWT==1.7.1 \
- --hash=sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e \
- --hash=sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96
-fasteners==0.17.3 \
- --hash=sha256:a9a42a208573d4074c77d041447336cf4e3c1389a256fd3e113ef59cf29b7980 \
- --hash=sha256:cae0772df265923e71435cc5057840138f4e8b6302f888a567d06ed8e1cbca03
-pluginbase==1.0.1 \
- --hash=sha256:ff6c33a98fce232e9c73841d787a643de574937069f0d18147028d70d7dee287
-MarkupSafe==2.1.1 \
- --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \
- --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \
- --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \
- --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \
- --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \
- --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \
- --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \
- --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \
- --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \
- --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \
- --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \
- --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \
- --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \
- --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \
- --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \
- --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \
- --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \
- --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \
- --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \
- --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \
- --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \
- --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \
- --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \
- --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \
- --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \
- --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \
- --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \
- --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \
- --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \
- --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \
- --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \
- --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \
- --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \
- --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \
- --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \
- --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \
- --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \
- --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \
- --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \
- --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7
-chardet==4.0.0 \
- --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
- --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
-idna==3.3 \
- --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \
- --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d
-
-
-### sip ###
-
-sip==6.5.1 \
- --hash=sha256:01a637b44c5918505801c3d56e1e010b8e86a4edee71c0bd8541c54387b57ae2 \
- --hash=sha256:13b09357615c2d8bcb23bf21c1637941ac8ff5f28b346c1ccad7efafa57673e9 \
- --hash=sha256:204f0240db8999a749d638a987b351861843e69239b811ec3d1881412c3706a6 \
- --hash=sha256:57e5ac40744c0f10a6c53dd45d2ef2c90e52f34a0210d8309e6563a07f914d0d \
- --hash=sha256:de1cb4004d75a3a236f82a69cd7a3e51ff76b414df412fea22bf433b28876e3f
-setuptools==59.4.0 \
- --hash=sha256:b4c634615a0cf5b02cf83c7bedffc8da0ca439f00e79452699454da6fbd4153d \
- --hash=sha256:feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060
-toml==0.10.2 \
- --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \
- --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f
-packaging==20.9 \
- --hash=sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5 \
- --hash=sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a
-pyparsing==3.0.7 \
- --hash=sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea \
- --hash=sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484
\ No newline at end of file
diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp
index 762eb91d6e..e235b78ef0 100644
--- a/src/FffGcodeWriter.cpp
+++ b/src/FffGcodeWriter.cpp
@@ -697,6 +697,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
constexpr double fill_overlap = 0; // raft line shouldn't be expanded - there is no boundary polygon printed
constexpr int infill_multiplier = 1; // rafts use single lines
constexpr int extra_infill_shift = 0;
+ constexpr bool fill_gaps = true;
Polygons raft_polygons; // should remain empty, since we only have the lines pattern for the raft...
std::optional last_planned_position = std::optional();
@@ -746,24 +747,37 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
const coord_t max_resolution = base_settings.get("meshfix_maximum_resolution");
const coord_t max_deviation = base_settings.get("meshfix_maximum_deviation");
- Infill infill_comp(
- EFillMethod::LINES, zig_zaggify_infill, connect_polygons, storage.raftOutline, gcode_layer.configs_storage.raft_base_config.getLineWidth(), line_spacing,
- fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
- max_resolution, max_deviation,
- wall_line_count, infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
- );
- std::vector raft_paths;
- infill_comp.generate(raft_paths, raft_polygons, raftLines, base_settings);
- if(!raft_paths.empty())
+ std::vector raft_outline_paths;
+ if (storage.primeRaftOutline.area() > 0)
{
- const GCodePathConfig& config = gcode_layer.configs_storage.raft_base_config;
- const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
- InsetOrderOptimizer wall_orderer(*this, storage, gcode_layer, base_settings, base_extruder_nr,
- config, config, config, config,
- retract_before_outer_wall, wipe_dist, wipe_dist, base_extruder_nr, base_extruder_nr, z_seam_config, raft_paths);
- wall_orderer.addToLayer();
+ raft_outline_paths.emplace_back(storage.primeRaftOutline);
+ }
+ raft_outline_paths.emplace_back(storage.raftOutline);
+
+ for (const Polygons& raft_outline_path : raft_outline_paths)
+ {
+ Infill infill_comp(
+ EFillMethod::LINES, zig_zaggify_infill, connect_polygons, raft_outline_path, gcode_layer.configs_storage.raft_base_config.getLineWidth(), line_spacing,
+ fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
+ max_resolution, max_deviation,
+ wall_line_count, infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
+ );
+ std::vector raft_paths;
+ infill_comp.generate(raft_paths, raft_polygons, raftLines, base_settings);
+ if (!raft_paths.empty())
+ {
+ const GCodePathConfig& config = gcode_layer.configs_storage.raft_base_config;
+ const ZSeamConfig z_seam_config(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false);
+ InsetOrderOptimizer wall_orderer(*this, storage, gcode_layer, base_settings, base_extruder_nr,
+ config, config, config, config,
+ retract_before_outer_wall, wipe_dist, wipe_dist, base_extruder_nr, base_extruder_nr, z_seam_config, raft_paths);
+ wall_orderer.addToLayer();
+ }
+ gcode_layer.addLinesByOptimizer(raftLines, gcode_layer.configs_storage.raft_base_config, SpaceFillType::Lines);
+
+ raft_polygons.clear();
+ raftLines.clear();
}
- gcode_layer.addLinesByOptimizer(raftLines, gcode_layer.configs_storage.raft_base_config, SpaceFillType::Lines);
// When we use raft, we need to make sure that all used extruders for this print will get primed on the first raft layer,
// and then switch back to the original extruder.
@@ -808,10 +822,17 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
Application::getInstance().communication->sendLayerComplete(layer_nr, z, interface_layer_height);
- Polygons raft_outline_path = storage.raftOutline.offset(-gcode_layer.configs_storage.raft_interface_config.getLineWidth() / 2); //Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
- raft_outline_path = Simplify(interface_settings).polygon(raft_outline_path); //Remove those micron-movements.
+ std::vector raft_outline_paths;
+ const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth() / 2; //Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
+ if (storage.primeRaftOutline.area() > 0)
+ {
+ raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset));
+ raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); //Remove those micron-movements.
+ }
+ raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset));
+ raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); //Remove those micron-movements.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
- Polygons raftLines;
+ Polygons raft_lines;
AngleDegrees fill_angle = (num_surface_layers + num_interface_layers - raft_interface_layer) % 2 ? 45 : 135; //90 degrees rotated from the first top layer.
constexpr bool zig_zaggify_infill = true;
constexpr bool connect_polygons = true; // why not?
@@ -825,15 +846,21 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
constexpr int zag_skip_count = 0;
constexpr coord_t pocket_size = 0;
- Infill infill_comp(
- EFillMethod::ZIG_ZAG, zig_zaggify_infill, connect_polygons, raft_outline_path, infill_outline_width, interface_line_spacing,
- fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
- interface_max_resolution, interface_max_deviation,
- wall_line_count, infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
+ for (const Polygons& raft_outline_path : raft_outline_paths)
+ {
+ Infill infill_comp(
+ EFillMethod::ZIG_ZAG, zig_zaggify_infill, connect_polygons, raft_outline_path, infill_outline_width, interface_line_spacing,
+ fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
+ interface_max_resolution, interface_max_deviation,
+ wall_line_count, infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
);
- std::vector raft_paths; //Should remain empty, since we have no walls.
- infill_comp.generate(raft_paths, raft_polygons, raftLines, interface_settings);
- gcode_layer.addLinesByOptimizer(raftLines, gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);
+ std::vector raft_paths; //Should remain empty, since we have no walls.
+ infill_comp.generate(raft_paths, raft_polygons, raft_lines, interface_settings);
+ gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);
+
+ raft_polygons.clear();
+ raft_lines.clear();
+ }
layer_plan_buffer.handle(gcode_layer, gcode);
last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition();
@@ -870,8 +897,15 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
Application::getInstance().communication->sendLayerComplete(layer_nr, z, surface_layer_height);
- Polygons raft_outline_path = storage.raftOutline.offset(-gcode_layer.configs_storage.raft_surface_config.getLineWidth() / 2); //Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
- raft_outline_path = Simplify(surface_settings).polygon(raft_outline_path); //Remove those micron-movements.
+ std::vector raft_outline_paths;
+ const coord_t small_offset = gcode_layer.configs_storage.raft_interface_config.getLineWidth() / 2; //Do this manually because of micron-movement created in corners when insetting a polygon that was offset with round joint type.
+ if (storage.primeRaftOutline.area() > 0)
+ {
+ raft_outline_paths.emplace_back(storage.primeRaftOutline.offset(-small_offset));
+ raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); //Remove those micron-movements.
+ }
+ raft_outline_paths.emplace_back(storage.raftOutline.offset(-small_offset));
+ raft_outline_paths.back() = Simplify(interface_settings).polygon(raft_outline_paths.back()); //Remove those micron-movements.
const coord_t infill_outline_width = gcode_layer.configs_storage.raft_interface_config.getLineWidth();
Polygons raft_lines;
AngleDegrees fill_angle = (num_surface_layers - raft_surface_layer) % 2 ? 45 : 135; //Alternate between -45 and +45 degrees, ending up 90 degrees rotated from the default skin angle.
@@ -887,15 +921,21 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage)
constexpr size_t zag_skip_count = 0;
constexpr coord_t pocket_size = 0;
- Infill infill_comp(
- EFillMethod::ZIG_ZAG, zig_zaggify_infill, connect_polygons, raft_outline_path, infill_outline_width, surface_line_spacing,
- fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
- surface_max_resolution, surface_max_deviation,
- wall_line_count, infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
+ for (const Polygons& raft_outline_path : raft_outline_paths)
+ {
+ Infill infill_comp(
+ EFillMethod::ZIG_ZAG, zig_zaggify_infill, connect_polygons, raft_outline_path, infill_outline_width, surface_line_spacing,
+ fill_overlap, infill_multiplier, fill_angle, z, extra_infill_shift,
+ surface_max_resolution, surface_max_deviation,
+ wall_line_count, infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
);
- std::vector raft_paths; //Should remain empty, since we have no walls.
- infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings);
- gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_surface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);
+ std::vector raft_paths; //Should remain empty, since we have no walls.
+ infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings);
+ gcode_layer.addLinesByOptimizer(raft_lines, gcode_layer.configs_storage.raft_surface_config, SpaceFillType::Lines, false, 0, 1.0, last_planned_position);
+
+ raft_polygons.clear();
+ raft_lines.clear();
+ }
layer_plan_buffer.handle(gcode_layer, gcode);
}
@@ -1510,6 +1550,7 @@ bool FffGcodeWriter::processMultiLayerInfill(const SliceDataStorage& storage, La
constexpr bool use_endpieces = true;
constexpr bool skip_some_zags = false;
constexpr size_t zag_skip_count = 0;
+ const bool fill_gaps = density_idx == 0; //Only fill gaps for the lowest density.
const LightningLayer * lightning_layer = nullptr;
if (mesh.lightning_generator)
@@ -1520,7 +1561,7 @@ bool FffGcodeWriter::processMultiLayerInfill(const SliceDataStorage& storage, La
part.infill_area_per_combine_per_density[density_idx][combine_idx], infill_line_width,
infill_line_distance_here, infill_overlap, infill_multiplier, infill_angle,
gcode_layer.z, infill_shift, max_resolution, max_deviation, wall_line_count,
- infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count,
+ infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count,
mesh.settings.get("cross_infill_pocket_size"));
infill_comp.generate(infill_paths, infill_polygons, infill_lines, mesh.settings, mesh.cross_fill_provider, lightning_layer, &mesh);
}
@@ -1679,6 +1720,7 @@ bool FffGcodeWriter::processSingleLayerInfill(const SliceDataStorage& storage, L
lightning_layer = &mesh.lightning_generator->getTreesForLayer(gcode_layer.getLayerNr());
}
+ const bool fill_gaps = density_idx == 0; //Only fill gaps in the lowest infill density pattern.
if (hasSkinEdgeSupport)
{
// infill region with skin above has to have at least one infill wall line
@@ -1689,10 +1731,8 @@ bool FffGcodeWriter::processSingleLayerInfill(const SliceDataStorage& storage, L
Infill infill_comp(pattern, zig_zaggify_infill, connect_polygons, infill_below_skin, infill_line_width,
infill_line_distance_here, overlap, infill_multiplier, infill_angle, gcode_layer.z,
infill_shift, max_resolution, max_deviation, skin_below_wall_count, infill_origin,
- skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size);
+ skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size);
infill_comp.generate(wall_tool_paths.back(), infill_polygons, infill_lines, mesh.settings, mesh.cross_fill_provider, lightning_layer, &mesh);
-
- // Fixme: CURA-7848 for libArachne.
if (density_idx < last_idx)
{
const coord_t cut_offset =
@@ -1727,10 +1767,8 @@ bool FffGcodeWriter::processSingleLayerInfill(const SliceDataStorage& storage, L
Infill infill_comp(pattern, zig_zaggify_infill, connect_polygons, in_outline, infill_line_width,
infill_line_distance_here, overlap, infill_multiplier, infill_angle, gcode_layer.z,
infill_shift, max_resolution, max_deviation, wall_line_count_here, infill_origin,
- skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size);
+ skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size);
infill_comp.generate(wall_tool_paths.back(), infill_polygons, infill_lines, mesh.settings, mesh.cross_fill_provider, lightning_layer, &mesh);
-
- // Fixme: CURA-7848 for libArachne.
if (density_idx < last_idx)
{
const coord_t cut_offset = get_cut_offset(zig_zaggify_infill, infill_line_width, wall_line_count);
@@ -1742,7 +1780,16 @@ bool FffGcodeWriter::processSingleLayerInfill(const SliceDataStorage& storage, L
}
wall_tool_paths.emplace_back(part.infill_wall_toolpaths); //The extra infill walls were generated separately. Add these too.
- const bool walls_generated = std::any_of(wall_tool_paths.cbegin(), wall_tool_paths.cend(), [](const std::vector& tp){ return !tp.empty(); });
+ const bool walls_generated =
+ std::any_of
+ (
+ wall_tool_paths.cbegin(),
+ wall_tool_paths.cend(),
+ [](const std::vector& tp)
+ {
+ return ! (tp.empty() || std::all_of(tp.begin(), tp.end(), [](const VariableWidthLines& vwl) { return vwl.empty(); }));
+ }
+ );
if(!infill_lines.empty() || !infill_polygons.empty() || walls_generated)
{
added_something = true;
@@ -1764,7 +1811,7 @@ bool FffGcodeWriter::processSingleLayerInfill(const SliceDataStorage& storage, L
else //So walls_generated must be true.
{
std::vector* start_paths = &wall_tool_paths[rand() % wall_tool_paths.size()];
- while(start_paths->empty()) //We know for sure (because walls_generated) that one of them is not empty. So randomise until we hit it. Should almost always be very quick.
+ while(start_paths->empty() || (*start_paths)[0].empty()) //We know for sure (because walls_generated) that one of them is not empty. So randomise until we hit it. Should almost always be very quick.
{
start_paths = &wall_tool_paths[rand() % wall_tool_paths.size()];
}
@@ -2413,6 +2460,7 @@ void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, La
coord_t max_deviation = mesh.settings.get("meshfix_maximum_deviation");
const Point infill_origin;
const bool skip_line_stitching = monotonic;
+ constexpr bool fill_gaps = true;
constexpr bool connected_zigzags = false;
constexpr bool use_endpieces = true;
constexpr bool skip_some_zags = false;
@@ -2423,7 +2471,7 @@ void FffGcodeWriter::processSkinPrintFeature(const SliceDataStorage& storage, La
pattern, zig_zaggify_infill, connect_polygons, area, config.getLineWidth(), config.getLineWidth() / skin_density, skin_overlap, infill_multiplier, skin_angle, gcode_layer.z, extra_infill_shift
, max_resolution, max_deviation
, wall_line_count, infill_origin,
- skip_line_stitching,
+ skip_line_stitching, fill_gaps,
connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
);
infill_comp.generate(skin_paths, skin_polygons, skin_lines, mesh.settings);
@@ -2716,11 +2764,12 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer
constexpr size_t wall_count = 0; // Walls are generated somewhere else, so their layers aren't vertically combined.
constexpr bool skip_stitching = false;
+ const bool fill_gaps = density_idx == 0; //Only fill gaps for one of the densities.
Infill infill_comp(support_pattern, zig_zaggify_infill, connect_polygons, area,
support_line_width, support_line_distance_here, current_support_infill_overlap - (density_idx == max_density_idx ? 0 : wall_line_count * support_line_width),
infill_multiplier, support_infill_angle, gcode_layer.z, support_shift,
max_resolution, max_deviation,
- wall_count, infill_origin, skip_stitching, support_connect_zigzags,
+ wall_count, infill_origin, skip_stitching, fill_gaps, support_connect_zigzags,
use_endpieces, skip_some_zags, zag_skip_count, pocket_size);
infill_comp.generate(wall_toolpaths_here, support_polygons, support_lines, infill_extruder.settings, storage.support.cross_fill_provider);
}
@@ -2855,6 +2904,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, Lay
constexpr size_t wall_line_count = 0;
const Point infill_origin;
constexpr bool skip_stitching = false;
+ constexpr bool fill_gaps = true;
constexpr bool use_endpieces = true;
constexpr bool connected_zigzags = false;
constexpr bool skip_some_zags = false;
@@ -2883,7 +2933,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, Lay
pattern, zig_zaggify_infill, connect_polygons, infill_outline, gcode_layer.configs_storage.support_roof_config.getLineWidth(),
support_roof_line_distance, support_roof_overlap, infill_multiplier, fill_angle, gcode_layer.z, extra_infill_shift,
max_resolution, max_deviation,
- wall_line_count, infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
+ wall_line_count, infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
);
Polygons roof_polygons;
std::vector roof_paths;
@@ -2952,6 +3002,7 @@ bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, L
constexpr size_t wall_line_count = 0;
const Point infill_origin;
constexpr bool skip_stitching = false;
+ constexpr bool fill_gaps = true;
constexpr bool use_endpieces = true;
constexpr bool connected_zigzags = false;
constexpr bool skip_some_zags = false;
@@ -2965,7 +3016,7 @@ bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, L
pattern, zig_zaggify_infill, connect_polygons, support_layer.support_bottom, gcode_layer.configs_storage.support_bottom_config.getLineWidth(),
support_bottom_line_distance, support_bottom_overlap, infill_multiplier, fill_angle, gcode_layer.z, extra_infill_shift,
max_resolution, max_deviation,
- wall_line_count, infill_origin, skip_stitching, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
+ wall_line_count, infill_origin, skip_stitching, fill_gaps, connected_zigzags, use_endpieces, skip_some_zags, zag_skip_count, pocket_size
);
Polygons bottom_polygons;
std::vector bottom_paths;
diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp
index 53d423d648..ad66bf37ff 100644
--- a/src/LayerPlan.cpp
+++ b/src/LayerPlan.cpp
@@ -1308,7 +1308,7 @@ void LayerPlan::spiralizeWallSlice(const GCodePathConfig& config, ConstPolygonRe
// when not smoothing, we get to the (unchanged) outline for this layer as quickly as possible so that the remainder of the
// outline wall has the correct direction - although this creates a little step, the end result is generally better because when the first
// outline wall has the wrong direction (due to it starting from the finish point of the last layer) the visual effect is very noticeable
- Point join_first_wall_at = LinearAlg2D::getClosestOnLineSegment(origin, wall[seam_vertex_idx], wall[(seam_vertex_idx + 1) % wall.size()]);
+ Point join_first_wall_at = LinearAlg2D::getClosestOnLineSegment(origin, wall[seam_vertex_idx % wall.size()], wall[(seam_vertex_idx + 1) % wall.size()]);
if (vSize(join_first_wall_at - origin) > 10)
{
constexpr Ratio flow = 1.0_r;
diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp
index ceb8ec1676..3bebe9758b 100644
--- a/src/PrimeTower.cpp
+++ b/src/PrimeTower.cpp
@@ -44,6 +44,7 @@ PrimeTower::PrimeTower()
enabled = scene.current_mesh_group->settings.get("prime_tower_enable")
&& scene.current_mesh_group->settings.get("prime_tower_min_volume") > 10
&& scene.current_mesh_group->settings.get("prime_tower_size") > 10;
+ would_have_actual_tower = enabled; // Assume so for now.
extruder_count = scene.extruders.size();
extruder_order.resize(extruder_count);
@@ -92,8 +93,8 @@ void PrimeTower::generateGroundpoly()
void PrimeTower::generatePaths(const SliceDataStorage& storage)
{
- enabled &= storage.max_print_height_second_to_last_extruder >= 0; //Maybe it turns out that we don't need a prime tower after all because there are no layer switches.
- if (enabled)
+ would_have_actual_tower = storage.max_print_height_second_to_last_extruder >= 0; //Maybe it turns out that we don't need a prime tower after all because there are no layer switches.
+ if (would_have_actual_tower && enabled)
{
generatePaths_denseInfill();
generateStartLocations();
@@ -168,7 +169,7 @@ void PrimeTower::generateStartLocations()
void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t prev_extruder, const size_t new_extruder) const
{
- if (!enabled)
+ if (! (enabled && would_have_actual_tower))
{
return;
}
@@ -178,7 +179,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, LayerPlan& gcode_la
}
const LayerIndex layer_nr = gcode_layer.getLayerNr();
- if (layer_nr > storage.max_print_height_second_to_last_extruder + 1)
+ if (layer_nr < 0 || layer_nr > storage.max_print_height_second_to_last_extruder + 1)
{
return;
}
diff --git a/src/PrimeTower.h b/src/PrimeTower.h
index f89240737d..a2f6510b52 100644
--- a/src/PrimeTower.h
+++ b/src/PrimeTower.h
@@ -1,4 +1,4 @@
-//Copyright (c) 2021 Ultimaker B.V.
+//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef PRIME_TOWER_H
@@ -44,6 +44,7 @@ class PrimeTower
public:
bool enabled; //!< Whether the prime tower is enabled.
+ bool would_have_actual_tower; //!< Whether there is an actual tower.
bool multiple_extruders_on_first_layer; //!< Whether multiple extruders are allowed on the first layer of the prime tower (e.g. when a raft is there)
Polygons outer_poly; //!< The outline of the outermost prime tower.
Polygons outer_poly_first_layer; //!< The outermost outline, plus optional brim on 'brim for prime tower' is enabled.
diff --git a/src/infill.cpp b/src/infill.cpp
index ac6568706c..9a164350db 100644
--- a/src/infill.cpp
+++ b/src/infill.cpp
@@ -117,7 +117,10 @@ void Infill::generate(std::vector& toolpaths, Polygons& resu
if(path.polygonLength() >= infill_line_width * 4) //Don't fill gaps that are very small (with paths less than 2 line widths long, 4 back and forth).
{
gap_filled_areas.add(path);
- thin_walls_only.push_back(extrusion);
+ if(fill_gaps)
+ {
+ thin_walls_only.push_back(extrusion);
+ }
}
}
}
diff --git a/src/infill.h b/src/infill.h
index 12ae8a76e1..0aa298e0fe 100644
--- a/src/infill.h
+++ b/src/infill.h
@@ -41,6 +41,7 @@ class Infill
size_t wall_line_count; //!< Number of walls to generate at the boundary of the infill region, spaced \ref infill_line_width apart
const Point infill_origin; //!< origin of the infill pattern
bool skip_line_stitching; //!< Whether to bypass the line stitching normally performed for polyline type infills
+ bool fill_gaps; //!< Whether to fill gaps in strips of infill that would be too thin to fit the infill lines. If disabled, those areas are left empty.
bool connected_zigzags; //!< (ZigZag) Whether endpieces of zigzag infill should be connected to the nearest infill line on both sides of the zigzag connector
bool use_endpieces; //!< (ZigZag) Whether to include endpieces: zigzag connector segments from one infill line to itself
bool skip_some_zags; //!< (ZigZag) Whether to skip some zags
@@ -66,6 +67,7 @@ class Infill
, size_t wall_line_count = 0
, const Point& infill_origin = Point()
, bool skip_line_stitching = false
+ , bool fill_gaps = true
, bool connected_zigzags = false
, bool use_endpieces = false
, bool skip_some_zags = false
@@ -88,6 +90,7 @@ class Infill
, wall_line_count(wall_line_count)
, infill_origin(infill_origin)
, skip_line_stitching(skip_line_stitching)
+ , fill_gaps(fill_gaps)
, connected_zigzags(connected_zigzags)
, use_endpieces(use_endpieces)
, skip_some_zags(skip_some_zags)
diff --git a/src/raft.cpp b/src/raft.cpp
index 3d9cf5a9ca..a3820cd2a1 100644
--- a/src/raft.cpp
+++ b/src/raft.cpp
@@ -18,11 +18,11 @@ namespace cura
void Raft::generate(SliceDataStorage& storage)
{
assert(storage.raftOutline.size() == 0 && "Raft polygon isn't generated yet, so should be empty!");
- const Settings& settings = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("adhesion_extruder_nr").settings;
+ const Settings& settings = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("raft_base_extruder_nr").settings;
const coord_t distance = settings.get("raft_margin");
constexpr bool include_support = true;
- constexpr bool include_prime_tower = true;
- storage.raftOutline = storage.getLayerOutlines(0, include_support, include_prime_tower).offset(distance, ClipperLib::jtRound);
+ constexpr bool dont_include_prime_tower = false; // Prime tower raft will be handled separately in 'storage.primeRaftOutline'; see below.
+ storage.raftOutline = storage.getLayerOutlines(0, include_support, dont_include_prime_tower).offset(distance, ClipperLib::jtRound);
const coord_t shield_line_width_layer0 = settings.get("skirt_brim_line_width");
if (storage.draft_protection_shield.size() > 0)
{
@@ -47,20 +47,45 @@ void Raft::generate(SliceDataStorage& storage)
const coord_t smoothing = settings.get("raft_smoothing");
storage.raftOutline = storage.raftOutline.offset(smoothing, ClipperLib::jtRound).offset(-smoothing, ClipperLib::jtRound); // remove small holes and smooth inward corners
}
+
+ if (storage.primeTower.enabled && ! storage.primeTower.would_have_actual_tower)
+ {
+ // Find out if the prime-tower part of the raft still needs to be printed, even if there is no actual tower.
+ // This will only happen if the different raft layers are printed by different extruders.
+ const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings;
+ const size_t base_extruder_nr = mesh_group_settings.get("raft_base_extruder_nr").extruder_nr;
+ const size_t interface_extruder_nr = mesh_group_settings.get("raft_interface_extruder_nr").extruder_nr;
+ const size_t surface_extruder_nr = mesh_group_settings.get("raft_surface_extruder_nr").extruder_nr;
+ if (base_extruder_nr == interface_extruder_nr && base_extruder_nr == surface_extruder_nr)
+ {
+ return;
+ }
+ }
+
+ storage.primeRaftOutline = storage.primeTower.outer_poly_first_layer.offset(distance, ClipperLib::jtRound);
+ if (settings.get("raft_remove_inside_corners"))
+ {
+ storage.primeRaftOutline = storage.primeRaftOutline.unionPolygons(storage.raftOutline);
+ storage.primeRaftOutline.makeConvex();
+ }
+ storage.primeRaftOutline = storage.primeRaftOutline.difference(storage.raftOutline); // In case of overlaps.
}
coord_t Raft::getTotalThickness()
{
- const ExtruderTrain& train = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("adhesion_extruder_nr");
- return train.settings.get("raft_base_thickness")
- + train.settings.get("raft_interface_layers") * train.settings.get("raft_interface_thickness")
- + train.settings.get("raft_surface_layers") * train.settings.get("raft_surface_thickness");
+ const Settings& mesh_group_settings =Application::getInstance().current_slice->scene.current_mesh_group->settings;
+ const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr");
+ const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr");
+ const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr");
+ return base_train.settings.get("raft_base_thickness")
+ + interface_train.settings.get("raft_interface_layers") * interface_train.settings.get("raft_interface_thickness")
+ + surface_train.settings.get("raft_surface_layers") * surface_train.settings.get("raft_surface_thickness");
}
coord_t Raft::getZdiffBetweenRaftAndLayer1()
{
const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings;
- const ExtruderTrain& train = mesh_group_settings.get("adhesion_extruder_nr");
+ const ExtruderTrain& train = mesh_group_settings.get("raft_surface_extruder_nr");
if (mesh_group_settings.get("adhesion_type") != EPlatformAdhesion::RAFT)
{
return 0;
@@ -94,12 +119,15 @@ coord_t Raft::getFillerLayerHeight()
size_t Raft::getTotalExtraLayers()
{
- const ExtruderTrain& train = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("adhesion_extruder_nr");
- if (train.settings.get("adhesion_type") != EPlatformAdhesion::RAFT)
+ const Settings& mesh_group_settings =Application::getInstance().current_slice->scene.current_mesh_group->settings;
+ const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr");
+ const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr");
+ const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr");
+ if (base_train.settings.get("adhesion_type") != EPlatformAdhesion::RAFT)
{
return 0;
}
- return 1 + train.settings.get("raft_interface_layers") + train.settings.get("raft_surface_layers") + getFillerLayerCount();
+ return 1 + interface_train.settings.get("raft_interface_layers") + surface_train.settings.get("raft_surface_layers") + getFillerLayerCount();
}
diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp
index 02684b2529..c6d741e5d2 100644
--- a/src/sliceDataStorage.cpp
+++ b/src/sliceDataStorage.cpp
@@ -595,12 +595,15 @@ Polygon SliceDataStorage::getMachineBorder(bool adhesion_offset) const
}
coord_t adhesion_size = 0; //Make sure there is enough room for the platform adhesion around support.
- const ExtruderTrain& adhesion_extruder = mesh_group_settings.get("adhesion_extruder_nr");
+ const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr");
+ const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr");
+ const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr");
+ const ExtruderTrain& skirt_brim_train = mesh_group_settings.get("skirt_brim_extruder_nr");
coord_t extra_skirt_line_width = 0;
const std::vector is_extruder_used = getExtrudersUsed();
for (size_t extruder_nr = 0; extruder_nr < Application::getInstance().current_slice->scene.extruders.size(); extruder_nr++)
{
- if (extruder_nr == adhesion_extruder.extruder_nr || !is_extruder_used[extruder_nr]) //Unused extruders and the primary adhesion extruder don't generate an extra skirt line.
+ if (extruder_nr == skirt_brim_train.extruder_nr || !is_extruder_used[extruder_nr]) //Unused extruders and the primary adhesion extruder don't generate an extra skirt line.
{
continue;
}
@@ -610,13 +613,23 @@ Polygon SliceDataStorage::getMachineBorder(bool adhesion_offset) const
switch (mesh_group_settings.get("adhesion_type"))
{
case EPlatformAdhesion::BRIM:
- adhesion_size = adhesion_extruder.settings.get("skirt_brim_line_width") * adhesion_extruder.settings.get("initial_layer_line_width_factor") * adhesion_extruder.settings.get("brim_line_count") + extra_skirt_line_width;
+ adhesion_size = skirt_brim_train.settings.get("skirt_brim_line_width")
+ * skirt_brim_train.settings.get("initial_layer_line_width_factor")
+ * skirt_brim_train.settings.get("brim_line_count") + extra_skirt_line_width;
break;
case EPlatformAdhesion::RAFT:
- adhesion_size = adhesion_extruder.settings.get("raft_margin");
+ adhesion_size = std::max({
+ base_train.settings.get("raft_margin"),
+ interface_train.settings.get("raft_margin"),
+ surface_train.settings.get("raft_margin")
+ });
break;
case EPlatformAdhesion::SKIRT:
- adhesion_size = adhesion_extruder.settings.get("skirt_gap") + adhesion_extruder.settings.get("skirt_brim_line_width") * adhesion_extruder.settings.get("initial_layer_line_width_factor") * adhesion_extruder.settings.get("skirt_line_count") + extra_skirt_line_width;
+ adhesion_size = skirt_brim_train.settings.get("skirt_gap")
+ + skirt_brim_train.settings.get("skirt_brim_line_width")
+ * skirt_brim_train.settings.get("initial_layer_line_width_factor")
+ * skirt_brim_train.settings.get("skirt_line_count")
+ + extra_skirt_line_width;
break;
case EPlatformAdhesion::NONE:
adhesion_size = 0;
diff --git a/src/sliceDataStorage.h b/src/sliceDataStorage.h
index 658932fb52..b131f38e57 100644
--- a/src/sliceDataStorage.h
+++ b/src/sliceDataStorage.h
@@ -1,4 +1,4 @@
-//Copyright (c) 2021 Ultimaker B.V.
+//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef SLICE_DATA_STORAGE_H
@@ -319,6 +319,7 @@ class SliceDataStorage : public NoCopy
Polygons skirt_brim[MAX_EXTRUDERS]; //!< Skirt and brim polygons per extruder, ordered from inner to outer polygons.
size_t skirt_brim_max_locked_part_order[MAX_EXTRUDERS]; //!< Some parts (like skirt) always need to be printed before parts like support-brim, so lock 0..n for each extruder, where n is the value saved in this array.
Polygons raftOutline; //Storage for the outline of the raft. Will be filled with lines when the GCode is generated.
+ Polygons primeRaftOutline; // ... the raft underneath the prime-tower will have to be printed first, if there is one. (When the raft has top layers with a different extruder for example.)
int max_print_height_second_to_last_extruder; //!< Used in multi-extrusion: the layer number beyond which all models are printed with the same extruder
std::vector max_print_height_per_extruder; //!< For each extruder the highest layer number at which it is used.
diff --git a/src/support.cpp b/src/support.cpp
index 4f088e4f4c..a6f407c86a 100644
--- a/src/support.cpp
+++ b/src/support.cpp
@@ -500,8 +500,11 @@ Polygons AreaSupport::join(const SliceDataStorage& storage, const Polygons& supp
break;
case EPlatformAdhesion::RAFT:
{
- const ExtruderTrain& raft_extruder = mesh_group_settings.get("adhesion_extruder_nr");
- adhesion_size = raft_extruder.settings.get("raft_margin");
+ adhesion_size = std::max({
+ mesh_group_settings.get("raft_base_extruder_nr").settings.get("raft_margin"),
+ mesh_group_settings.get("raft_interface_extruder_nr").settings.get("raft_margin"),
+ mesh_group_settings.get("raft_surface_extruder_nr").settings.get("raft_margin")
+ });
break;
}
case EPlatformAdhesion::SKIRT:
diff --git a/src/utils/Simplify.h b/src/utils/Simplify.h
index c24a7e33bc..a5a8d95e65 100644
--- a/src/utils/Simplify.h
+++ b/src/utils/Simplify.h
@@ -322,7 +322,7 @@ class Simplify
{
return; //Cannot remove edge without shifting a long edge. Don't remove anything.
}
- const coord_t intersection_deviation = LinearAlg2D::getDist2FromLine(intersection, before_to, after_from);
+ const coord_t intersection_deviation = LinearAlg2D::getDist2FromLineSegment(before_to, intersection, after_from);
if(intersection_deviation <= max_deviation * max_deviation) //Intersection point doesn't deviate too much. Use it!
{
to_delete[vertex] = true;
diff --git a/src/utils/ThreadPool.h b/src/utils/ThreadPool.h
index 1acf4852d4..f9042fc9eb 100644
--- a/src/utils/ThreadPool.h
+++ b/src/utils/ThreadPool.h
@@ -230,7 +230,7 @@ void run_multiple_producers_ordered_consumer(ptrdiff_t first, ptrdiff_t last, P&
assert(thread_pool);
assert(max_pending_per_worker > 0);
const size_t max_pending = max_pending_per_worker * (thread_pool->thread_count() + 1);
- MultipleProducersOrderedConsumer(first, last, std::forward(producer), std::forward(consumer), max_pending).run(*thread_pool);
+ MultipleProducersOrderedConsumer(first, last, std::forward
(producer), std::forward(consumer), max_pending).run(*thread_pool);
}
template
@@ -300,7 +300,7 @@ class MultipleProducersOrderedConsumer
ptrdiff_t produce(lock_t& lock)
{
ptrdiff_t produced_idx = write_idx++;
- item_t* slot = &queue[produced_idx % max_pending];
+ item_t* slot = &queue[(produced_idx + max_pending) % max_pending];
assert(produced_idx < last_idx);
// Unlocks global mutex while producing an item
@@ -319,7 +319,7 @@ class MultipleProducersOrderedConsumer
void consume_many(lock_t& lock)
{
assert(read_idx < write_idx);
- for (item_t* slot = &queue[read_idx % max_pending]; *slot ; slot = &queue[read_idx % max_pending])
+ for (item_t* slot = &queue[(read_idx + max_pending) % max_pending]; *slot ; slot = &queue[(read_idx + max_pending) % max_pending])
{
// Unlocks global mutex while consuming an item
lock.unlock();