├── .chglog
├── CHANGELOG.tpl.md
└── config.yml
├── .github
└── workflows
│ ├── deploy-linux-appimage.yml
│ ├── deploy-windows.yml
│ └── sonarcloud.yml
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── CMakeLists.txt
├── LICENCE.txt
├── README.md
├── ci
├── buildappimage.sh
├── buildsonarcloud.sh
└── deploywindows.sh
├── cmake
├── FindGcov.cmake
├── FindLcov.cmake
└── Findcodecov.cmake
├── doc
├── Bulge2Arc2.png
├── Capture.PNG
├── configuration.png
├── logo.png
├── pocket.gif
├── screen.png
└── simulation.gif
├── reference
├── 11812-Article Text-33790-1-10-20150414.pdf
├── ApproximatingNURBScurvesbyarcsplines_GMP2000.pdf
├── Optimal_Single_Biarc_Fitting_and_its_Applications.pdf
└── bs.pdf
├── resource
├── CMakeLists.txt
├── dxfplotter.desktop
├── dxfplotter.png
├── icons
│ ├── application-exit.svg
│ ├── configure.svg
│ ├── document-export.svg
│ ├── document-open.svg
│ ├── document-save-as.svg
│ ├── document-save.svg
│ ├── edit-copy.svg
│ ├── go-down.svg
│ ├── go-up.svg
│ ├── layer-lower.svg
│ ├── layer-raise.svg
│ ├── layer-visible-off.svg
│ ├── layer-visible-on.svg
│ ├── list-add.svg
│ ├── list-remove.svg
│ ├── path-inset.svg
│ ├── path-outset.svg
│ ├── playback-pause.svg
│ ├── playback-start.svg
│ ├── pocket-shape.svg
│ ├── resizecol.svg
│ ├── set-origin.svg
│ ├── show-path-outline.svg
│ ├── simulate.svg
│ ├── transform-rotate.svg
│ └── zoom-in.svg
└── resource.qrc
├── sonar-project.properties
├── src
├── CMakeLists.txt
├── common
│ ├── CMakeLists.txt
│ ├── aggregable.h
│ ├── enum.h
│ ├── exception.h
│ └── function.h
├── config
│ ├── CMakeLists.txt
│ ├── config.cpp
│ ├── config.h.in
│ ├── config_gen.py
│ ├── group.h
│ ├── list.h
│ ├── node.cpp
│ ├── node.h
│ ├── property.h
│ └── utils.h
├── exporter
│ ├── CMakeLists.txt
│ ├── dxfplot
│ │ ├── CMakeLists.txt
│ │ ├── exporter.cpp
│ │ └── exporter.h
│ ├── gcode
│ │ ├── CMakeLists.txt
│ │ ├── exporter.cpp
│ │ ├── exporter.h
│ │ ├── metadata.cpp
│ │ ├── metadata.h
│ │ ├── postprocessor.cpp
│ │ └── postprocessor.h
│ └── renderer
│ │ ├── CMakeLists.txt
│ │ ├── passesiterator.cpp
│ │ ├── passesiterator.h
│ │ ├── renderer.cpp
│ │ └── renderer.h
├── geometry
│ ├── CMakeLists.txt
│ ├── arc.cpp
│ ├── arc.h
│ ├── bezier.cpp
│ ├── bezier.h
│ ├── biarc.cpp
│ ├── biarc.h
│ ├── bulge.cpp
│ ├── bulge.h
│ ├── cavcutils.h
│ ├── circle.cpp
│ ├── circle.h
│ ├── cubicspline.cpp
│ ├── cubicspline.h
│ ├── filter
│ │ ├── CMakeLists.txt
│ │ ├── assembler.cpp
│ │ ├── assembler.h
│ │ ├── cleaner.cpp
│ │ ├── cleaner.h
│ │ ├── removeexactduplicate.cpp
│ │ ├── removeexactduplicate.h
│ │ ├── sorter.cpp
│ │ └── sorter.h
│ ├── line.cpp
│ ├── line.h
│ ├── pocketer.cpp
│ ├── pocketer.h
│ ├── polyline.cpp
│ ├── polyline.h
│ ├── quadraticspline.cpp
│ ├── quadraticspline.h
│ ├── rect.cpp
│ ├── rect.h
│ ├── spline.cpp
│ ├── spline.h
│ └── utils.h
├── importer
│ ├── CMakeLists.txt
│ ├── dxf
│ │ ├── CMakeLists.txt
│ │ ├── entityimporter.cpp
│ │ ├── entityimporter.h
│ │ ├── importer.cpp
│ │ ├── importer.h
│ │ ├── interface.cpp
│ │ ├── interface.h
│ │ ├── layer.cpp
│ │ ├── layer.h
│ │ └── utils.h
│ └── dxfplot
│ │ ├── CMakeLists.txt
│ │ ├── importer.cpp
│ │ └── importer.h
├── main.cpp
├── model
│ ├── CMakeLists.txt
│ ├── application.cpp
│ ├── application.h
│ ├── document.cpp
│ ├── document.h
│ ├── documentmodelobserver.h
│ ├── layer.cpp
│ ├── layer.h
│ ├── offsettedpath.cpp
│ ├── offsettedpath.h
│ ├── path.cpp
│ ├── path.h
│ ├── pathgroupsettings.cpp
│ ├── pathgroupsettings.h
│ ├── pathsettings.cpp
│ ├── pathsettings.h
│ ├── renderable.cpp
│ ├── renderable.h
│ ├── simulation.cpp
│ ├── simulation.h
│ ├── task.cpp
│ └── task.h
├── serializer
│ ├── CMakeLists.txt
│ ├── access.h
│ ├── bulge.h
│ ├── layer.h
│ ├── offsettedpath.h
│ ├── path.h
│ ├── pathsettings.h
│ ├── polyline.h
│ ├── qvector2d.h
│ ├── renderable.h
│ └── task.h
└── view
│ ├── CMakeLists.txt
│ ├── dialogs
│ ├── CMakeLists.txt
│ ├── mirror.cpp
│ ├── mirror.h
│ ├── setorigin.cpp
│ ├── setorigin.h
│ ├── settings
│ │ ├── CMakeLists.txt
│ │ ├── entry.h
│ │ ├── group.h
│ │ ├── list.cpp
│ │ ├── list.h
│ │ ├── settings.cpp
│ │ ├── settings.h
│ │ ├── treemodel.cpp
│ │ └── treemodel.h
│ ├── transform.cpp
│ └── transform.h
│ ├── info.cpp
│ ├── info.h
│ ├── mainwindow.cpp
│ ├── mainwindow.h
│ ├── profile.cpp
│ ├── profile.h
│ ├── simulation
│ ├── CMakeLists.txt
│ ├── internal
│ │ ├── CMakeLists.txt
│ │ ├── scene.cpp
│ │ ├── scene.h
│ │ ├── tool.cpp
│ │ ├── tool.h
│ │ ├── toolpath.cpp
│ │ ├── toolpath.h
│ │ ├── viewport.cpp
│ │ └── viewport.h
│ ├── simulation.cpp
│ └── simulation.h
│ ├── task
│ ├── CMakeLists.txt
│ ├── layertreemodel.cpp
│ ├── layertreemodel.h
│ ├── path.cpp
│ ├── path.h
│ ├── pathlistmodel.cpp
│ ├── pathlistmodel.h
│ ├── task.cpp
│ └── task.h
│ ├── transform.h
│ └── view2d
│ ├── CMakeLists.txt
│ ├── basicpathitem.cpp
│ ├── basicpathitem.h
│ ├── bulgepainter.cpp
│ ├── bulgepainter.h
│ ├── offsettedpolylinepathitem.cpp
│ ├── offsettedpolylinepathitem.h
│ ├── pointpathitem.cpp
│ ├── pointpathitem.h
│ ├── polylinepathitem.cpp
│ ├── polylinepathitem.h
│ ├── rubberband.cpp
│ ├── rubberband.h
│ ├── viewport.cpp
│ └── viewport.h
├── template
├── CMakeLists.txt
├── config.xml
└── uic
│ ├── CMakeLists.txt
│ ├── dialogs
│ ├── CMakeLists.txt
│ ├── mirror.ui
│ ├── setorigin.ui
│ ├── settings
│ │ ├── CMakeLists.txt
│ │ ├── group.ui
│ │ ├── list.ui
│ │ └── settings.ui
│ └── transform.ui
│ ├── info.ui
│ ├── mainwindow.ui
│ ├── path.ui
│ ├── profile.ui
│ ├── simulation
│ ├── CMakeLists.txt
│ └── simulation.ui
│ └── task.ui
├── test
├── CMakeLists.txt
├── a.out
├── arc.cpp
├── assembler.cpp
├── bulge.cpp
├── dxfplotexporter.cpp
├── dxfplotimporter.cpp
├── exporterfixture.cpp
├── exporterfixture.h
├── gcodeexporter.cpp
├── main.cpp
├── path.cpp
├── pathsettings.cpp
├── pocketer.cpp
├── polyline.cpp
├── polylineutils.cpp
├── polylineutils.h
├── serializer.cpp
├── simulation.cpp
├── spline.cpp
├── task.cpp
├── testarc.cpp
├── testbezier.cpp
├── testexport.cpp
└── verticalspeed.cpp
└── thirdparty
├── CMakeLists.txt
└── libdxfrw
├── CMakeLists.txt
├── drw_base.cpp
├── drw_base.h
├── drw_classes.cpp
├── drw_classes.h
├── drw_entities.cpp
├── drw_entities.h
├── drw_header.cpp
├── drw_header.h
├── drw_interface.h
├── drw_objects.cpp
├── drw_objects.h
├── intern
├── drw_cptable932.h
├── drw_cptable936.h
├── drw_cptable949.h
├── drw_cptable950.h
├── drw_cptables.h
├── drw_dbg.cpp
├── drw_dbg.h
├── drw_textcodec.cpp
├── drw_textcodec.h
├── dwgbuffer.cpp
├── dwgbuffer.h
├── dwgreader.cpp
├── dwgreader.h
├── dwgreader15.cpp
├── dwgreader15.h
├── dwgreader18.cpp
├── dwgreader18.h
├── dwgreader21.cpp
├── dwgreader21.h
├── dwgreader24.cpp
├── dwgreader24.h
├── dwgreader27.cpp
├── dwgreader27.h
├── dwgutil.cpp
├── dwgutil.h
├── dxfreader.cpp
├── dxfreader.h
├── dxfwriter.cpp
├── dxfwriter.h
├── rscodec.cpp
└── rscodec.h
├── libdwgr.cpp
├── libdwgr.h
├── libdxfrw.cpp
├── libdxfrw.h
└── main_doc.h
/.chglog/CHANGELOG.tpl.md:
--------------------------------------------------------------------------------
1 | {{ range .Versions }}
2 |
3 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }}
4 |
5 | > {{ datetime "2006-01-02" .Tag.Date }}
6 |
7 | {{ range .CommitGroups -}}
8 | ### {{ .Title }}
9 |
10 | {{ range .Commits -}}
11 | * {{ .Subject }}
12 | {{ end }}
13 | {{ end -}}
14 |
15 | {{- if .NoteGroups -}}
16 | {{ range .NoteGroups -}}
17 | ### {{ .Title }}
18 |
19 | {{ range .Notes }}
20 | {{ .Body }}
21 | {{ end }}
22 | {{ end -}}
23 | {{ end -}}
24 | {{ end -}}
--------------------------------------------------------------------------------
/.chglog/config.yml:
--------------------------------------------------------------------------------
1 | style: github
2 | template: CHANGELOG.tpl.md
3 | info:
4 | title: CHANGELOG
5 | repository_url: https://github.com/panzergame/dxfplotter
6 | options:
7 | commits:
8 | # filters:
9 | # Type:
10 | # - feat
11 | # - fix
12 | # - perf
13 | # - refactor
14 | commit_groups:
15 | # title_maps:
16 | # feat: Features
17 | # fix: Bug Fixes
18 | # perf: Performance Improvements
19 | # refactor: Code Refactoring
20 | header:
21 | pattern: "^(\\w*)\\:\\s(.*)$"
22 | pattern_maps:
23 | - Type
24 | - Subject
25 | notes:
26 | keywords:
27 | - BREAKING CHANGE
--------------------------------------------------------------------------------
/.github/workflows/deploy-linux-appimage.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_dispatch:
3 | push:
4 | # Sequence of patterns matched against refs/tags
5 | tags:
6 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
7 |
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v2
14 | with:
15 | submodules: true
16 | - name: Install package
17 | run: |
18 | sudo apt-get update
19 | sudo apt-get -y install qtbase5-dev qt3d5-dev libqt5svg5-dev freeglut3-dev libfuse2
20 | - name: Build and test
21 | run: ci/buildappimage.sh
22 | - name: Create Release
23 | uses: softprops/action-gh-release@v1
24 | with:
25 | files: "dxfplotter*.AppImage"
26 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-windows.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_dispatch:
3 | push:
4 | # Sequence of patterns matched against refs/tags
5 | tags:
6 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
7 |
8 | jobs:
9 | build:
10 | runs-on: windows-latest
11 | steps:
12 | - name: Cache Qt
13 | id: cache-qt
14 | uses: actions/cache@v1 # not v2!
15 | with:
16 | path: ../Qt
17 | key: ${{ runner.os }}-QtCache
18 |
19 | - name: Install Qt
20 | uses: jurplel/install-qt-action@v2
21 | with:
22 | cached: ${{ steps.cache-qt.outputs.cache-hit }}
23 | - uses: lukka/get-cmake@latest
24 | - name: Add msbuild to PATH
25 | uses: microsoft/setup-msbuild@v1.1
26 | - name: Install jinja2
27 | shell: bash
28 | run: python -m pip install jinja2
29 | - name: Install zip
30 | shell: bash
31 | run: choco install -y zip
32 | - name: Checkout
33 | uses: actions/checkout@v2
34 | with:
35 | submodules: true
36 | - name: CMake
37 | shell: bash
38 | run: |
39 | mkdir build
40 | cd build
41 | cmake -DBUILD_TESTING=OFF ..
42 | - name: Build
43 | run: msbuild build\dxfplotter.sln /property:Configuration=Release
44 | - name: Deploy Qt
45 | shell: bash
46 | run: ci/deploywindows.sh
47 | - name: Create Release
48 | uses: softprops/action-gh-release@v1
49 | with:
50 | files: "dxfplotter*.zip"
51 |
52 |
--------------------------------------------------------------------------------
/.github/workflows/sonarcloud.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_dispatch:
3 | push:
4 | branches:
5 | - "**"
6 |
7 | jobs:
8 | static_analysis:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v2
13 | with:
14 | submodules: true
15 | - name: Install package
16 | run: |
17 | sudo apt-get update
18 | sudo apt-get -y install qtbase5-dev qt3d5-dev libqt5svg5-dev freeglut3-dev lcov
19 | - name: Install build wrapper
20 | run: |
21 | wget http://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip
22 | unzip build-wrapper-linux-x86.zip
23 | - name: Install sonar scanner
24 | run: |
25 | wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.2.2472-linux.zip
26 | unzip sonar-scanner-cli-4.6.2.2472-linux.zip
27 | - name: Build and scan
28 | run: ci/buildsonarcloud.sh
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.kdev4
2 | build/
3 | data/
4 | .cache/
5 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "thirdparty/nanoflann"]
2 | path = thirdparty/nanoflann
3 | url = https://github.com/jlblancoc/nanoflann.git
4 | [submodule "thirdparty/cavaliercontours"]
5 | path = thirdparty/cavaliercontours
6 | url = https://github.com/jbuckmccready/CavalierContours.git
7 | [submodule "thirdparty/cereal"]
8 | path = thirdparty/cereal
9 | url = https://github.com/USCiLab/cereal.git
10 | [submodule "thirdparty/yaml-cpp"]
11 | path = thirdparty/yaml-cpp
12 | url = https://github.com/jbeder/yaml-cpp.git
13 | [submodule "thirdparty/fmt"]
14 | path = thirdparty/fmt
15 | url = https://github.com/fmtlib/fmt.git
16 |
--------------------------------------------------------------------------------
/LICENCE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WliliITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/ci/buildappimage.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -x
4 | set -e
5 |
6 | # building in temporary directory to keep system clean
7 | # use RAM disk if possible (as in: not building on CI system like Travis, and RAM disk is available)
8 | if [ "$CI" == "" ] && [ -d /dev/shm ]; then
9 | TEMP_BASE=/dev/shm
10 | else
11 | TEMP_BASE=/tmp
12 | fi
13 |
14 | BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" appimage-build-XXXXXX)
15 |
16 | # make sure to clean up build dir, even if errors occur
17 | cleanup () {
18 | if [ -d "$BUILD_DIR" ]; then
19 | rm -rf "$BUILD_DIR"
20 | fi
21 | }
22 | trap cleanup EXIT
23 |
24 | # store repo root as variable
25 | REPO_ROOT=$(readlink -f $(dirname $(dirname $0)))
26 | OLD_CWD=$(readlink -f .)
27 |
28 | # generate release name
29 | COMMIT=$(git rev-parse --short HEAD)
30 | TAG=$(git describe --tags)
31 | RELEASE_NAME="dxfplotter-$TAG-$COMMIT-x86_64-linux"
32 |
33 | # switch to build dir
34 | pushd "$BUILD_DIR"
35 |
36 | # configure build files with CMake
37 | # we need to explicitly set the install prefix, as CMake's default is /usr/local for some reason...
38 | cmake "$REPO_ROOT" -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTING=OFF
39 |
40 | # build project and install files into AppDir
41 | make -j$(nproc)
42 | make install DESTDIR=AppDir
43 |
44 | # now, build AppImage using linuxdeployqt
45 | wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
46 |
47 | # make them executable
48 | chmod +x linuxdeploy*.AppImage
49 |
50 | # linuxdeployqt seems to need desktop and icon files to be placed at the root of AppDir
51 | cp AppDir/usr/share/icons/hicolor/256x256/apps/dxfplotter.png AppDir/usr/share/applications/dxfplotter.desktop AppDir
52 |
53 | # generate the AppImage
54 | # use -unsupported-allow-new-glibc for newest linux distribution
55 | ./linuxdeployqt-continuous-x86_64.AppImage AppDir/usr/bin/dxfplotter -appimage -extra-plugins=iconengines,platformthemes/libqgtk3.so,renderers/libopenglrenderer.so -unsupported-allow-new-glibc
56 |
57 | # move built AppImage back into original CWD
58 | mv dxfplotter*.AppImage "$OLD_CWD"/"$RELEASE_NAME".AppImage
59 |
--------------------------------------------------------------------------------
/ci/buildsonarcloud.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -x
4 | set -e
5 |
6 | # building in temporary directory to keep system clean
7 | # use RAM disk if possible (as in: not building on CI system like Travis, and RAM disk is available)
8 | if [ "$CI" == "" ] && [ -d /dev/shm ]; then
9 | TEMP_BASE=/dev/shm
10 | else
11 | TEMP_BASE=/tmp
12 | fi
13 |
14 | BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" analyse-sonarcloud-XXXXXX)
15 |
16 | # make sure to clean up build dir, even if errors occur
17 | cleanup () {
18 | if [ -d "$BUILD_DIR" ]; then
19 | rm -rf "$BUILD_DIR"
20 | fi
21 | }
22 | trap cleanup EXIT
23 |
24 | # store repo root as variable
25 | REPO_ROOT=$(readlink -f $(dirname $(dirname $0)))
26 | OLD_CWD=$(readlink -f .)
27 |
28 | # switch to build dir
29 | pushd "$BUILD_DIR"
30 |
31 | # configure build files with CMake
32 | # we need to explicitly set the install prefix, as CMake's default is /usr/local for some reason...
33 | cmake "$REPO_ROOT" -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON
34 |
35 | # Wraps the compilation with the Build Wrapper to generate configuration (used
36 | # later by the SonarQube Scanner) into the "bw-output" folder
37 | "$REPO_ROOT"/build-wrapper-linux-x86/build-wrapper-linux-x86-64 \
38 | --out-dir bw-output cmake \
39 | --build .
40 | # Test project
41 | ctest -VV
42 |
43 | # Generate coverage report
44 | make gcov
45 |
46 | # Scan project
47 | "$REPO_ROOT"/sonar-scanner-4.6.2.2472-linux/bin/sonar-scanner -Dsonar.host.url=https://sonarcloud.io -Dproject.settings="$REPO_ROOT"/sonar-project.properties -Dsonar.projectBaseDir="$REPO_ROOT" -Dsonar.cfamily.gcov.reportsPath="$BUILD_DIR"
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ci/deploywindows.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -x
4 | set -e
5 |
6 | # generate release name
7 | COMMIT=$(git rev-parse --short HEAD)
8 | TAG=$(git describe --tags)
9 | RELEASE_NAME="dxfplotter-$TAG-$COMMIT-x86_64-windows"
10 |
11 | BUILD_DIR="build"
12 | BINARY_NAME="dxfplotter.exe"
13 | BINARY_PATH="${BUILD_DIR}/Release/${BINARY_NAME}"
14 |
15 | DEPLOY_DIR="${RELEASE_NAME}"
16 | mkdir $DEPLOY_DIR
17 | cp $BINARY_PATH $DEPLOY_DIR
18 |
19 | windeployqt --release --dir $DEPLOY_DIR "${DEPLOY_DIR}/${BINARY_NAME}"
20 |
21 | zip -r "${RELEASE_NAME}.zip" $RELEASE_NAME
22 |
--------------------------------------------------------------------------------
/doc/Bulge2Arc2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/Bulge2Arc2.png
--------------------------------------------------------------------------------
/doc/Capture.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/Capture.PNG
--------------------------------------------------------------------------------
/doc/configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/configuration.png
--------------------------------------------------------------------------------
/doc/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/logo.png
--------------------------------------------------------------------------------
/doc/pocket.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/pocket.gif
--------------------------------------------------------------------------------
/doc/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/screen.png
--------------------------------------------------------------------------------
/doc/simulation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/doc/simulation.gif
--------------------------------------------------------------------------------
/reference/11812-Article Text-33790-1-10-20150414.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/reference/11812-Article Text-33790-1-10-20150414.pdf
--------------------------------------------------------------------------------
/reference/ApproximatingNURBScurvesbyarcsplines_GMP2000.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/reference/ApproximatingNURBScurvesbyarcsplines_GMP2000.pdf
--------------------------------------------------------------------------------
/reference/Optimal_Single_Biarc_Fitting_and_its_Applications.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/reference/Optimal_Single_Biarc_Fitting_and_its_Applications.pdf
--------------------------------------------------------------------------------
/reference/bs.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/reference/bs.pdf
--------------------------------------------------------------------------------
/resource/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | qt5_add_resources(SOURCES resource.qrc)
2 |
3 | add_library(resource ${SOURCES})
4 |
5 | install(FILES dxfplotter.png DESTINATION share/icons/hicolor/256x256/apps/)
6 | install(FILES dxfplotter.desktop DESTINATION share/applications/)
7 |
--------------------------------------------------------------------------------
/resource/dxfplotter.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Categories=Utility;
3 | Type=Application
4 | Icon=dxfplotter
5 | Name=dxfplotter
6 | Exec=dxfplotter
7 |
8 |
--------------------------------------------------------------------------------
/resource/dxfplotter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/resource/dxfplotter.png
--------------------------------------------------------------------------------
/resource/icons/application-exit.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/resource/icons/configure.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/document-export.svg:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/resource/icons/document-open.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/document-save-as.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/document-save.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/edit-copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/resource/icons/go-down.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/resource/icons/go-up.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/resource/icons/layer-lower.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/resource/icons/layer-raise.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/resource/icons/layer-visible-off.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/layer-visible-on.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/list-add.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/list-remove.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/path-inset.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/resource/icons/path-outset.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/resource/icons/playback-pause.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/resource/icons/playback-start.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/resource/icons/pocket-shape.svg:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/resource/icons/resizecol.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/set-origin.svg:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/resource/icons/show-path-outline.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/resource/icons/simulate.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/transform-rotate.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/icons/zoom-in.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/resource/resource.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dxfplotter.png
5 |
6 |
7 | icons/application-exit.svg
8 | icons/configure.svg
9 | icons/document-export.svg
10 | icons/document-open.svg
11 | icons/document-save-as.svg
12 | icons/document-save.svg
13 | icons/edit-copy.svg
14 | icons/go-down.svg
15 | icons/go-up.svg
16 | icons/layer-lower.svg
17 | icons/layer-raise.svg
18 | icons/layer-visible-off.svg
19 | icons/layer-visible-on.svg
20 | icons/list-add.svg
21 | icons/list-remove.svg
22 | icons/path-inset.svg
23 | icons/path-outset.svg
24 | icons/playback-pause.svg
25 | icons/playback-start.svg
26 | icons/pocket-shape.svg
27 | icons/resizecol.svg
28 | icons/set-origin.svg
29 | icons/show-path-outline.svg
30 | icons/simulate.svg
31 | icons/transform-rotate.svg
32 | icons/zoom-in.svg
33 |
34 |
35 |
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.organization=panzergame
2 | sonar.projectKey=dxfplotter
3 | sonar.sources=src
4 | sonar.exclusions=thirdparty/**/*
5 | sonar.cfamily.build-wrapper-output=bw-output
6 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(common)
2 | add_subdirectory(config)
3 | add_subdirectory(exporter)
4 | add_subdirectory(geometry)
5 | add_subdirectory(importer)
6 | add_subdirectory(model)
7 | add_subdirectory(serializer)
8 | add_subdirectory(view)
9 |
--------------------------------------------------------------------------------
/src/common/CMakeLists.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panzergame/dxfplotter/144d320e199756ed6b7766f7c3ed35c555dd57b5/src/common/CMakeLists.txt
--------------------------------------------------------------------------------
/src/common/aggregable.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace common
9 | {
10 |
11 | template
12 | class Aggregable
13 | {
14 | public:
15 | using UPtr = std::unique_ptr- ;
16 |
17 | using List = std::vector
- ;
18 | using ListPtr = std::vector
- ;
19 | using ListCPtr = std::vector;
20 | using ListUPtr = std::vector;
21 |
22 | template
23 | using Array = std::array
- ;
24 | template
25 | using ArrayPtr = std::array
- ;
26 |
27 | using SetPtr = std::set
- ;
28 |
29 | using Pair = Array<2>;
30 | using PairPtr = ArrayPtr<2>;
31 | };
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/common/enum.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace common::enumerate
6 | {
7 |
8 | template
9 | inline std::initializer_list All();
10 |
11 | template
12 | inline std::string toString(const EnumType &value);
13 |
14 | template
15 | inline EnumType fromString(const std::string &value);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/common/exception.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace common
7 | {
8 |
9 | class FileCouldNotOpenException : public std::exception
10 | {
11 | };
12 |
13 | class GCodeFormatException : public std::runtime_error
14 | {
15 | private:
16 | template
17 | static std::string errorMessage(const std::string &format, const char *error, Args&& ... args)
18 | {
19 | std::ostringstream stream;
20 | stream << "Formatting error, format \"" << format << "\" with arguments";
21 |
22 | ((stream << ' ' << args), ...);
23 | stream << ": " << error;
24 |
25 | return stream.str();
26 | }
27 |
28 | public:
29 | template
30 | explicit GCodeFormatException(const std::string &format, const char *error, Args&& ... args)
31 | :std::runtime_error(errorMessage(format, error, std::forward(args)...))
32 | {
33 | }
34 | };
35 |
36 | class ImportCouldNotFindToolConfigException : public std::exception
37 | {
38 | };
39 |
40 | class ImportCouldNotFindProfileConfigException : public std::exception
41 | {
42 | };
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/common/function.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace common
4 | {
5 |
6 | template
7 | struct MemberFunctionTraits;
8 |
9 | template
10 | struct MemberFunctionTraits<_Return (_Object::*)(Args ...)>
11 | {
12 | using Object = _Object;
13 | using Return = _Return;
14 | };
15 |
16 | template
17 | struct MemberFunctionTraits<_Return (_Object::*)(Args ...) const>
18 | {
19 | using Object = _Object;
20 | using Return = _Return;
21 | };
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/config/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set_property(SOURCE config.h PROPERTY SKIP_AUTOGEN ON)
2 |
3 | set(SRC
4 | config.cpp
5 | node.cpp
6 |
7 | config.h
8 | group.h
9 | list.h
10 | node.h
11 | property.h
12 | )
13 |
14 | add_library(config ${SRC})
15 | add_dependencies(config generate-config)
16 |
17 | add_custom_command(
18 | OUTPUT config.h
19 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/config_gen.py ${TEMPLATE_DIR}/config.xml ${CMAKE_CURRENT_SOURCE_DIR} config.h.in config.h
20 | DEPENDS config.h.in ${TEMPLATE_DIR}/config.xml config_gen.py
21 | )
22 |
23 | add_custom_target(generate-config DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/config.h)
24 |
--------------------------------------------------------------------------------
/src/config/config.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace config
8 | {
9 |
10 | Config::Config(const std::string &filePath)
11 | :m_filePath(filePath)
12 | {
13 | try {
14 | m_yamlRoot = YAML::LoadFile(filePath);
15 | }
16 | catch (const YAML::BadFile&) {
17 | qInfo() << "Initializing configuration from defaults";
18 | }
19 |
20 | // Instantiation of root group
21 | m_root = Root(m_yamlRoot);
22 | }
23 |
24 | Config::Config(const Config &other)
25 | :m_filePath(other.m_filePath),
26 | m_yamlRoot(Clone(other.m_yamlRoot)),
27 | m_root(m_yamlRoot)
28 | {
29 | }
30 |
31 | Config::~Config()
32 | {
33 | save();
34 | }
35 |
36 | Root &Config::root()
37 | {
38 | return m_root;
39 | }
40 |
41 | const Root &Config::root() const
42 | {
43 | return m_root;
44 | }
45 |
46 | void Config::save() const
47 | {
48 | std::ofstream outStream(m_filePath);
49 | outStream << m_yamlRoot;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/config/group.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace config
8 | {
9 |
10 | /** @brief A configuration group.
11 | */
12 | template
13 | class Group : public Node
14 | {
15 | protected:
16 | using Children = std::tuple;
17 |
18 | const Children& children() const
19 | {
20 | return m_children;
21 | }
22 |
23 | Children& children()
24 | {
25 | return m_children;
26 | }
27 |
28 | void setChildren(const Children& children)
29 | {
30 | m_children = children;
31 | }
32 |
33 | private:
34 | Children m_children;
35 |
36 | public:
37 | explicit Group(const std::string& name, const std::string &description)
38 | :Node(name, description)
39 | {
40 | }
41 |
42 | Group() = default;
43 |
44 | template
45 | void visitChildren(Visitor &&visitor)
46 | {
47 | std::apply([&visitor](auto&&... arg) {((visitor(arg)), ...);}, m_children);
48 | }
49 |
50 | template
51 | void visitChildren(Visitor &&visitor) const
52 | {
53 | std::apply([&visitor](auto&&... arg) {((visitor(arg)), ...);}, m_children);
54 | }
55 | };
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/config/node.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | namespace config
5 | {
6 |
7 | Node::Node(const std::string &name, const std::string &description)
8 | :m_name(name),
9 | m_description(description)
10 | {
11 | }
12 |
13 | const std::string &Node::name() const
14 | {
15 | return m_name;
16 | }
17 |
18 | const std::string &Node::description() const
19 | {
20 | return m_description;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/config/node.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace config
8 | {
9 |
10 | class Node
11 | {
12 | private:
13 | std::string m_name;
14 | std::string m_description;
15 |
16 | public:
17 | explicit Node(const std::string &name, const std::string &description);
18 | Node() = default;
19 |
20 | const std::string &name() const;
21 | const std::string &description() const;
22 | };
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/config/property.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace config
8 | {
9 |
10 | template
11 | class Property : public Node
12 | {
13 | private:
14 | YAML::Node m_yamlNode;
15 |
16 | public:
17 | explicit Property(const std::string& name, const std::string &description, const ValueType &defaultValue, YAML::Node yamlNode)
18 | :Node(name, description),
19 | m_yamlNode(yamlNode)
20 | {
21 | // Assign default value if node isn't defined
22 | if (!m_yamlNode.IsDefined()) {
23 | *this = defaultValue;
24 | }
25 | }
26 |
27 | Property() = default;
28 |
29 | operator ValueType() const
30 | {
31 | return fromSerializable(m_yamlNode);
32 | }
33 |
34 | Property &operator=(const ValueType &value)
35 | {
36 | m_yamlNode = toSerializable(value);
37 | return *this;
38 | }
39 | };
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/config/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace config
8 | {
9 |
10 | template
11 | inline std::enable_if_t, Type> toSerializable(const Type &value)
12 | {
13 | return value;
14 | }
15 |
16 | template
17 | inline std::enable_if_t, std::string> toSerializable(const EnumType& value)
18 | {
19 | return common::enumerate::toString(value);
20 | }
21 |
22 | template
23 | inline Type fromSerializable(const YAML::Node &node)
24 | {
25 | if constexpr(std::is_enum_v) {
26 | return common::enumerate::fromString(node.as());
27 | }
28 | else {
29 | return node.as();
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/exporter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(dxfplot)
2 | add_subdirectory(gcode)
3 | add_subdirectory(renderer)
4 |
--------------------------------------------------------------------------------
/src/exporter/dxfplot/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | exporter.cpp
3 |
4 | exporter.h
5 | )
6 |
7 | add_library(exporter-dxfplot ${SRC})
8 | add_dependencies(exporter-dxfplot generate-config)
9 | add_coverage(exporter-dxfplot)
10 |
--------------------------------------------------------------------------------
/src/exporter/dxfplot/exporter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace exporter::dxfplot
8 | {
9 |
10 | void Exporter::operator()(const model::Document& document, std::ostream &output) const
11 | {
12 | Archive archive(output);
13 | save(archive, document);
14 | }
15 |
16 | void Exporter::save(Archive &archive, const model::Document& document) const
17 | {
18 | archive(cereal::make_nvp("task", document.task()));
19 | archive(cereal::make_nvp("profile_name", document.profileConfig().name()));
20 | archive(cereal::make_nvp("tool_name", document.toolConfig().name()));
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/exporter/dxfplot/exporter.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 |
9 | namespace exporter::dxfplot
10 | {
11 |
12 | class Exporter
13 | {
14 | public:
15 | explicit Exporter() = default;
16 |
17 | void operator()(const model::Document& document, std::ostream &output) const;
18 |
19 | private:
20 | using Archive = cereal::JSONOutputArchive;
21 |
22 | void save(Archive &archive, const model::Document& document) const;
23 | };
24 |
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/exporter/gcode/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | exporter.cpp
3 | metadata.cpp
4 | postprocessor.cpp
5 |
6 | exporter.h
7 | metadata.h
8 | postprocessor.h
9 | )
10 |
11 | add_library(exporter-gcode ${SRC})
12 | add_dependencies(exporter-gcode generate-config)
13 | add_coverage(exporter-gcode)
14 |
--------------------------------------------------------------------------------
/src/exporter/gcode/exporter.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 |
9 | namespace exporter::gcode
10 | {
11 |
12 | class PathPostProcessor;
13 |
14 | class Exporter
15 | {
16 | public:
17 | enum Options
18 | {
19 | None = 0,
20 | ExportConfig = (1 << 0),
21 | ExportMetadata = (1 << 1)
22 | };
23 |
24 | private:
25 | const config::Tools::Tool &m_tool;
26 | const config::Profiles::Profile &m_profile;
27 | const Options m_options;
28 |
29 | public:
30 | explicit Exporter(const config::Tools::Tool& tool, const config::Profiles::Profile& profile, Options options = None);
31 | ~Exporter() = default;
32 |
33 | void operator()(const model::Document& document, std::ostream &output) const;
34 | };
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/src/exporter/gcode/metadata.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | namespace exporter::gcode
13 | {
14 |
15 | std::string Metadata::fastPlaneMoveGCode(const QVector2D &to) const
16 | {
17 | std::ostringstream output;
18 | PostProcessor postprocessor(m_gcode, output);
19 | postprocessor.fastPlaneMove(to);
20 | return output.str();
21 | }
22 |
23 | std::string Metadata::fastDepthMoveGCode(float to) const
24 | {
25 | std::ostringstream output;
26 | PostProcessor postprocessor(m_gcode, output);
27 | postprocessor.retractDepth(to);
28 | return output.str();
29 | }
30 |
31 | QJsonArray Metadata::boundingRectGcodes() const
32 | {
33 | std::initializer_list gcodes{
34 | fastDepthMoveGCode(m_retractDepth),
35 | fastPlaneMoveGCode(m_boundingRect.bottomLeft()),
36 | fastPlaneMoveGCode(m_boundingRect.bottomRight()),
37 | fastPlaneMoveGCode(m_boundingRect.topRight()),
38 | fastPlaneMoveGCode(m_boundingRect.topLeft()),
39 | fastPlaneMoveGCode(m_boundingRect.bottomLeft()),
40 | fastPlaneMoveGCode(QVector2D(0.0f, 0.0f)),
41 | fastDepthMoveGCode(0.0f)
42 | };
43 |
44 | QJsonArray jsonGcodes;
45 | for (const std::string &gcode : gcodes) {
46 | jsonGcodes.push_back(QString::fromStdString(gcode));
47 | }
48 |
49 | return jsonGcodes;
50 | }
51 |
52 | QJsonDocument Metadata::toJson() const
53 | {
54 | QJsonObject root;
55 | root["bounding_rect_gcodes"] = boundingRectGcodes();
56 |
57 | QJsonDocument document(root);
58 | return document;
59 | }
60 |
61 | Metadata::Metadata(const model::Document& document, const config::Profiles::Profile::Gcode& gcode, float retractDepth)
62 | :m_boundingRect(document.task().visibleBoundingRect()),
63 | m_gcode(gcode),
64 | m_retractDepth((retractDepth))
65 | {
66 | }
67 |
68 | std::string Metadata::toComment() const
69 | {
70 | const QJsonDocument& jsonDocument = toJson();
71 |
72 | return "; metadata_json = " + jsonDocument.toJson(QJsonDocument::Compact).toStdString() + "\n";
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/exporter/gcode/metadata.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | namespace model
9 | {
10 |
11 | class Document;
12 |
13 | }
14 |
15 | class QJsonObject;
16 |
17 | namespace exporter::gcode
18 | {
19 |
20 | class Metadata
21 | {
22 | private:
23 | const geometry::Rect m_boundingRect;
24 | const config::Profiles::Profile::Gcode& m_gcode;
25 | const float m_retractDepth;
26 |
27 | std::string fastPlaneMoveGCode(const QVector2D &to) const;
28 | std::string fastDepthMoveGCode(float to) const;
29 | QJsonArray boundingRectGcodes() const;
30 | QJsonDocument toJson() const;
31 |
32 | public:
33 | explicit Metadata(const model::Document& document, const config::Profiles::Profile::Gcode& gcode, float retractDepth);
34 |
35 | std::string toComment() const;
36 | };
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/exporter/gcode/postprocessor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | namespace exporter::gcode
11 | {
12 |
13 | class PostProcessor
14 | {
15 | private:
16 | std::ostream &m_stream;
17 |
18 | protected:
19 | const config::Profiles::Profile::Gcode& m_gcode;
20 |
21 | /** Print a command to stream with a format and a list of named arguments
22 | * @param format A fmt valid format string.
23 | * @param args List of named arguments
24 | */
25 | template
26 | void print(const std::string &format, Args&& ...args)
27 | {
28 | try {
29 | m_stream << fmt::format(format, std::forward(args)...) << "\n";
30 | }
31 | catch (const fmt::format_error &exception) {
32 | throw common::GCodeFormatException(format, exception.what(), fmt::to_string(args.name)...);
33 | }
34 | }
35 |
36 | public:
37 | void preCut(float intensity);
38 | void postCut();
39 | void planeLinearMove(const QVector2D &to, float feedRate);
40 | void depthLinearMove(float depth, float feedRate);
41 | void cwArcMove(const QVector2D &relativeCenter, const QVector2D &to, float feedRate);
42 | void ccwArcMove(const QVector2D &relativeCenter, const QVector2D &to, float feedRate);
43 | void fastPlaneMove(const QVector2D &to);
44 | void retractDepth(float depth);
45 | void processBulge(const geometry::Bulge &bulge, float planeFeedRate);
46 | void processLine(const geometry::Bulge &bulge, float planeFeedRate);
47 | void processArc(const geometry::Bulge &bulge, float planeFeedRate);
48 |
49 | explicit PostProcessor(const config::Profiles::Profile::Gcode& gcode, std::ostream &stream);
50 | };
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/exporter/renderer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | passesiterator.cpp
3 | renderer.cpp
4 |
5 | passesiterator.h
6 | renderer.h
7 | )
8 |
9 | add_library(exporter-renderer ${SRC})
10 | add_dependencies(exporter-renderer generate-config)
11 | add_coverage(exporter-renderer)
12 |
--------------------------------------------------------------------------------
/src/exporter/renderer/passesiterator.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | bool PassesIterator::needPolylineInverse() const
4 | {
5 | return (!m_closed || m_cuttingBackward);
6 | }
7 |
8 | const geometry::Polyline &PassesIterator::polylineForward() const
9 | {
10 | return m_cuttingBackward ? m_polylineInverse : m_polyline;
11 | }
12 |
13 | const geometry::Polyline &PassesIterator::polylineBackward() const
14 | {
15 | return m_cuttingBackward ? m_polyline : m_polylineInverse;
16 | }
17 |
18 | PassesIterator::PassesIterator(const geometry::Polyline &polyline, geometry::CuttingDirection direction)
19 | :m_closed(polyline.isClosed()),
20 | m_cuttingBackward(direction == geometry::CuttingDirection::BACKWARD),
21 | m_polyline(polyline),
22 | m_polylineInverse(needPolylineInverse() ? m_polyline.inverse() : geometry::Polyline())
23 | {
24 | }
25 |
26 | const geometry::Polyline &PassesIterator::operator*() const
27 | {
28 | if (m_closed || m_odd) {
29 | return polylineForward();
30 | }
31 | return polylineBackward();
32 | }
33 |
34 | PassesIterator &PassesIterator::operator++()
35 | {
36 | m_odd = !m_odd;
37 |
38 | return *this;
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/src/exporter/renderer/passesiterator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | // Return next polyline to convert
6 | class PassesIterator
7 | {
8 | private:
9 | bool m_odd = true;
10 | const bool m_closed;
11 | const bool m_cuttingBackward;
12 | const geometry::Polyline& m_polyline;
13 | const geometry::Polyline m_polylineInverse;
14 |
15 | bool needPolylineInverse() const;
16 | const geometry::Polyline &polylineForward() const;
17 | const geometry::Polyline &polylineBackward() const;
18 |
19 | public:
20 | explicit PassesIterator(const geometry::Polyline &polyline, geometry::CuttingDirection direction);
21 |
22 | const geometry::Polyline &operator*() const;
23 | PassesIterator &operator++();
24 | };
25 |
26 |
--------------------------------------------------------------------------------
/src/exporter/renderer/renderer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
--------------------------------------------------------------------------------
/src/geometry/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(filter)
2 |
3 | set(SRC
4 | arc.cpp
5 | bezier.cpp
6 | biarc.cpp
7 | bulge.cpp
8 | circle.cpp
9 | cubicspline.cpp
10 | line.cpp
11 | pocketer.cpp
12 | polyline.cpp
13 | quadraticspline.cpp
14 | rect.cpp
15 | spline.cpp
16 |
17 | arc.h
18 | bezier.h
19 | biarc.h
20 | bulge.h
21 | circle.h
22 | cubicspline.h
23 | line.h
24 | polyline.h
25 | quadraticspline.h
26 | spline.h
27 | rect.h
28 | utils.h
29 | )
30 |
31 | add_library(geometry ${SRC})
32 | add_coverage(geometry)
33 |
--------------------------------------------------------------------------------
/src/geometry/arc.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | namespace geometry
5 | {
6 |
7 | Arc::Arc(const Circle &circle, const QVector2D &start, const QVector2D &end,
8 | float starAngle, float endAngle)
9 | :Circle(circle),
10 | m_start(start),
11 | m_end(end),
12 | m_startAngle(starAngle),
13 | m_endAngle(endAngle)
14 | {
15 | if (orientation() == Orientation::CCW) {
16 | m_endAngle = EnsureEndGreater(m_startAngle, m_endAngle);
17 | assert(m_startAngle <= m_endAngle);
18 | }
19 | else {
20 | m_startAngle = EnsureEndGreater(m_endAngle, m_startAngle);
21 | assert(m_endAngle <= m_startAngle);
22 | }
23 |
24 | m_spanAngle = m_endAngle - m_startAngle;
25 | }
26 |
27 | const QVector2D &Arc::start() const
28 | {
29 | return m_start;
30 | }
31 |
32 | const QVector2D &Arc::end() const
33 | {
34 | return m_end;
35 | }
36 |
37 | float Arc::startAngle() const
38 | {
39 | return m_startAngle;
40 | }
41 |
42 | float Arc::endAngle() const
43 | {
44 | return m_endAngle;
45 | }
46 |
47 | float Arc::spanAngle() const
48 | {
49 | return m_spanAngle;
50 | }
51 |
52 | float Arc::length() const
53 | {
54 | return std::abs(m_spanAngle) * radius();
55 | }
56 |
57 | QVector2D Arc::pointAtAngle(float angle) const
58 | {
59 | const QVector2D relativeNormalizedPoint(std::cos(angle), std::sin(angle));
60 | const QVector2D point = (center() + relativeNormalizedPoint * radius());
61 | return point;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/geometry/arc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry
6 | {
7 |
8 | /** Arcs are considered as angle clamped circles
9 | */
10 | class Arc : public Circle
11 | {
12 | private:
13 | QVector2D m_start;
14 | QVector2D m_end;
15 | float m_startAngle;
16 | float m_endAngle;
17 | float m_spanAngle;
18 |
19 | public:
20 | explicit Arc(const Circle &circle, const QVector2D &start, const QVector2D &end,
21 | float starAngle, float endAngle);
22 |
23 | const QVector2D &start() const;
24 | const QVector2D &end() const;
25 | float startAngle() const;
26 | float endAngle() const;
27 | float spanAngle() const;
28 |
29 | float length() const;
30 |
31 | QVector2D pointAtAngle(float angle) const;
32 |
33 | template
34 | void approximateToLinesVisit(float maxError, Visitor &&visitor) const
35 | {
36 | // Calculate the angle step to not exceed allowed error (distance from line to arc).
37 | const float angleStep = std::fmax(std::acos(1.0f - maxError) * 2.0f, maxError);
38 |
39 | if (orientation() == geometry::Orientation::CCW) {
40 | for (float angle = m_startAngle + angleStep, end = m_endAngle; angle < end; angle += angleStep) {
41 | visitor(pointAtAngle(angle));
42 | }
43 | }
44 | else {
45 | for (float angle = m_startAngle - angleStep, end = m_endAngle; angle > end; angle -= angleStep) {
46 | visitor(pointAtAngle(angle));
47 | }
48 | }
49 |
50 | visitor(m_end);
51 | }
52 | };
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/geometry/bezier.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 |
9 | #include
10 |
11 | namespace geometry
12 | {
13 |
14 | class Bezier : public common::Aggregable
15 | {
16 | private:
17 | using Complex = std::complex;
18 | using InflexionPoints = std::array;
19 |
20 | QVector2D m_point1;
21 | QVector2D m_point2;
22 | QVector2D m_control1;
23 | QVector2D m_control2;
24 |
25 | static bool isRealInflexionPoint(const Bezier::Complex &point);
26 |
27 | InflexionPoints inflexions() const;
28 | QVector2D derivativeAt(float t) const;
29 |
30 | QVector2D findNearestPointWithTangent(const QVector2D &point, const QVector2D& tangent, float maxError) const;
31 |
32 | public:
33 | explicit Bezier(const QVector2D &p1, const QVector2D &c1,
34 | const QVector2D &c2, const QVector2D &p2);
35 | Bezier() = default;
36 |
37 | const QVector2D &point1() const;
38 | const QVector2D &point2() const;
39 | const QVector2D &control1() const;
40 | const QVector2D &control2() const;
41 |
42 | QVector2D at(float t) const;
43 |
44 | float approximateLength() const;
45 |
46 | Pair split(float t) const;
47 | Pair splitHalf() const;
48 | /// Split bezier keeping only convex shape.
49 | List splitToConvex() const;
50 |
51 | std::optional toBiarc() const;
52 | Polyline toLine() const;
53 |
54 | bool isPoint() const;
55 |
56 | float maxError(const Biarc &biarc) const;
57 | };
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/geometry/biarc.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | namespace geometry
9 | {
10 |
11 | Orientation Biarc::orientation() const
12 | {
13 | const float det = (m_middle.x() - m_point1.x()) * (m_middle.y() + m_point1.y()) +
14 | (m_point2.x() - m_middle.x()) * (m_point2.y() + m_middle.y()) +
15 | (m_point1.x() - m_point2.x()) * (m_point1.y() + m_point2.y());
16 |
17 | return (det < 0.0f) ? Orientation::CW : Orientation::CCW;
18 | }
19 |
20 | Biarc::Biarc(const QVector2D& point1, const QVector2D& middle, const QVector2D& point2,
21 | const QVector2D& tangent1, const QVector2D& tangent2)
22 | :m_point1(point1),
23 | m_point2(point2),
24 | m_middle(middle),
25 | m_tangent1(tangent1),
26 | m_tangent2(tangent2),
27 | m_line1(middle - point1),
28 | m_line2(middle - point2)
29 | {
30 | }
31 |
32 | const QVector2D &Biarc::middle() const
33 | {
34 | return m_middle;
35 | }
36 |
37 | QVector2D Biarc::tangentAtMiddle() const
38 | {
39 | // Rotate line by PI/2
40 | const QVector2D normalizedLine1 = m_line1.normalized();
41 | const QVector2D perpendicularLine1 = PerpendicularLine(normalizedLine1);
42 |
43 | // Tangent at middle is the reflect of tangent at start by perpendicular line start to end.
44 | return ReflectLine(m_tangent1.normalized(), perpendicularLine1);
45 | }
46 |
47 | float Biarc::approximateLength() const
48 | {
49 | return (m_point1 - m_middle).length() + (m_point2 - m_middle).length();
50 | }
51 |
52 | Polyline Biarc::toLinePolyline() const
53 | {
54 | const Bulge bulge(m_point1, m_point2, 0.0f);
55 | return Polyline({bulge});
56 | }
57 |
58 | Polyline Biarc::toPolyline() const
59 | {
60 | /* Angle from end to start line with arc tangent at start point is double of
61 | * bulge tangent angle.
62 | */
63 |
64 | // Half angle from tangent1 to line1
65 | const float thetab1 = (LineAngle(m_line1) - LineAngle(m_tangent1)) / 2.0f;
66 | // Half angle from line2 to tangent2
67 | const float thetab2 = (LineAngle(m_tangent2) - LineAngle(m_line2)) / 2.0f;
68 |
69 | const Bulge b1(m_point1, m_middle, std::tan(thetab1));
70 | const Bulge b2(m_middle, m_point2, std::tan(thetab2));
71 |
72 | return Polyline({b1, b2});
73 | }
74 |
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/src/geometry/biarc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | namespace geometry
11 | {
12 |
13 | class Biarc : public common::Aggregable
14 | {
15 | private:
16 | QVector2D m_point1;
17 | QVector2D m_point2;
18 | /// Intersection point of the arcs
19 | QVector2D m_middle;
20 | /// Tangent at point1
21 | QVector2D m_tangent1;
22 | /// Tangent at point1
23 | QVector2D m_tangent2;
24 | /// Line from point1 to middle
25 | QVector2D m_line1;
26 | /// Line from point2 to middle
27 | QVector2D m_line2;
28 |
29 | Orientation orientation() const;
30 |
31 | public:
32 | explicit Biarc(const QVector2D &point1, const QVector2D &middle, const QVector2D &point2,
33 | const QVector2D &tangent1, const QVector2D &tangent2);
34 |
35 | const QVector2D &middle() const;
36 | QVector2D tangentAtMiddle() const;
37 |
38 | float approximateLength() const;
39 |
40 | Polyline toLinePolyline() const;
41 | Polyline toPolyline() const;
42 | };
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/geometry/bulge.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | namespace geometry
19 | {
20 |
21 | class Bulge : public common::Aggregable
22 | {
23 | friend serializer::Access;
24 |
25 | private:
26 | QVector2D m_start;
27 | QVector2D m_end;
28 |
29 | float m_tangent;
30 |
31 | float arcRadius() const;
32 | QVector2D relativeArcCenter() const;
33 | Point2DList arcBoundingPoints() const;
34 |
35 | public:
36 | /** Define a bulge
37 | * @param start Starting point of the bulge
38 | * @param end Ending point of the bulge
39 | * @param tangent Tangent of a thourth of the arc angle.
40 | * Negative tangent means the arc goes clockwise from start to end,
41 | * otherwise anti clockwise from start to end.
42 | */
43 | explicit Bulge(const QVector2D &start, const QVector2D &end, float tangent);
44 | explicit Bulge(const cavc::PlineVertex &v1, const cavc::PlineVertex &v2);
45 | explicit Bulge() = default;
46 |
47 | const QVector2D &start() const;
48 | QVector2D &start();
49 | const QVector2D &end() const;
50 | QVector2D &end();
51 | float tangent() const;
52 | float &tangent();
53 |
54 | float length() const;
55 |
56 | Rect boundingRect() const;
57 |
58 | /// Change direction
59 | void invert();
60 | /// Transform to line, means tangent is 0.
61 | void linify();
62 |
63 | // Extend bulge start point
64 | Bulge extendStart(const QVector2D &start) const;
65 | // Extend bulge end point
66 | Bulge extendEnd(const QVector2D &end) const;
67 |
68 | bool isLine() const;
69 | bool isArc() const;
70 | Orientation orientation() const;
71 |
72 | Circle toCircle() const;
73 | Arc toArc() const;
74 | Line toLine() const;
75 |
76 | void transform(const QTransform &matrix);
77 |
78 | bool operator==(const Bulge& other) const;
79 |
80 | bool equalsInversed(const Bulge& other) const;
81 | };
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/geometry/cavcutils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace cavc::utils
6 | {
7 |
8 | // absolute threshold to be used for comparing reals generally
9 | template <> constexpr double realThreshold() { return 1e-12; }
10 |
11 | // absolute threshold to be used for reals in common geometric computation (e.g. to check for
12 | // singularities)
13 | template <> constexpr double realPrecision() { return 1e-9; }
14 |
15 | // absolute threshold to be used for joining slices together at end points
16 | template <> constexpr double sliceJoinThreshold() { return 1e-8; }
17 |
18 | // absolute threshold to be used for pruning invalid slices for offset
19 | template <> constexpr double offsetThreshold() { return 1e-8; }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/geometry/circle.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace geometry
4 | {
5 |
6 | Circle::Circle(const QVector2D ¢er, float radius, Orientation orientation)
7 | :m_center(center),
8 | m_radius(radius),
9 | m_orientation(orientation)
10 | {
11 | }
12 |
13 | const QVector2D &Circle::center() const
14 | {
15 | return m_center;
16 | }
17 |
18 | float Circle::radius() const
19 | {
20 | return m_radius;
21 | }
22 |
23 | Orientation Circle::orientation() const
24 | {
25 | return m_orientation;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/geometry/circle.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry
6 | {
7 |
8 | class Circle
9 | {
10 | private:
11 | QVector2D m_center;
12 | float m_radius;
13 | Orientation m_orientation;
14 |
15 | public:
16 | explicit Circle(const QVector2D ¢er, float radius, Orientation orientation);
17 |
18 | const QVector2D ¢er() const;
19 | float radius() const;
20 | Orientation orientation() const;
21 | };
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/geometry/cubicspline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry
6 | {
7 |
8 | class CubicSpline : public Spline
9 | {
10 | private:
11 | Point2DList convertClosedToCubicBezierPoints() const;
12 | Point2DList convertOpenedToCubicBezierPoints() const;
13 |
14 | Bezier::List pointsToBeziers(const Point2DList &bezierPoints) const;
15 |
16 | public:
17 | explicit CubicSpline(Point2DList &&points, bool closed);
18 |
19 | Bezier::List toBeziers() const;
20 | };
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/geometry/filter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | assembler.cpp
3 | cleaner.cpp
4 | removeexactduplicate.cpp
5 | sorter.cpp
6 |
7 | assembler.h
8 | cleaner.h
9 | removeexactduplicate.h
10 | sorter.h
11 | )
12 |
13 | add_library(geometry-filter ${SRC})
14 | add_coverage(geometry-filter)
15 |
--------------------------------------------------------------------------------
/src/geometry/filter/cleaner.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry::filter
6 | {
7 |
8 | /** @brief Clean polyline via merging of small bulges.
9 | */
10 | class Cleaner
11 | {
12 | private:
13 | Polyline::List m_polylines;
14 |
15 | public:
16 | explicit Cleaner(Polyline::List &&polylines, float minimumPolylineLength, float minimumArcLength);
17 |
18 | Polyline::List &&polylines();
19 | };
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/geometry/filter/removeexactduplicate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry::filter
6 | {
7 |
8 | /** @brief Remove exact duplicate of polylines
9 | */
10 | class RemoveExactDuplicate
11 | {
12 | private:
13 | Polyline::List m_polylines;
14 |
15 | struct UndirectedPolyline : common::Aggregable
16 | {
17 | QVector2D start;
18 | QVector2D end;
19 |
20 | enum class Direction
21 | {
22 | Normal,
23 | Opposite
24 | } direction;
25 | int index;
26 | const Polyline *polyline;
27 |
28 | UndirectedPolyline() = default;
29 | explicit UndirectedPolyline(const QVector2D &start, const QVector2D &end, const Polyline &polyline, int index, Direction direction);
30 |
31 | bool operator<(const UndirectedPolyline &other) const;
32 | bool operator==(const UndirectedPolyline &other) const;
33 | };
34 |
35 | using PolylineMaskList = std::vector;
36 |
37 | UndirectedPolyline::List buildPolylinesMap(const Polyline::List& polylines) const;
38 | PolylineMaskList buildPolylineMaskWithoutDuplicate(const UndirectedPolyline::List polylineMap, int nbPolylines) const;
39 | void filterPolylines(Polyline::List &&polylines, PolylineMaskList polylineMask);
40 |
41 | public:
42 | explicit RemoveExactDuplicate(Polyline::List &&polylines);
43 |
44 | Polyline::List &&polylines();
45 | };
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/geometry/filter/sorter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace geometry::filter
4 | {
5 |
6 | Sorter::Sorter(Polyline::List &&polylines)
7 | :m_polylines(polylines.size())
8 | {
9 | struct PolylineLength
10 | {
11 | Polyline *polyline;
12 | float length;
13 |
14 | PolylineLength() = default;
15 |
16 | explicit PolylineLength(Polyline &polyline)
17 | :polyline(&polyline),
18 | length(polyline.length())
19 | {
20 | }
21 |
22 | bool operator<(const PolylineLength& other) const
23 | {
24 | return length < other.length;
25 | }
26 | };
27 |
28 | std::vector polylinesLength(polylines.size());
29 | std::transform(polylines.begin(), polylines.end(), polylinesLength.begin(),
30 | [](Polyline& polyline){ return PolylineLength(polyline); });
31 |
32 | std::sort(polylinesLength.begin(), polylinesLength.end());
33 |
34 | std::transform(polylinesLength.begin(), polylinesLength.end(), m_polylines.begin(),
35 | [](PolylineLength& polylineLength){ return std::move(*polylineLength.polyline); });
36 | }
37 |
38 | Polyline::List &&Sorter::polylines()
39 | {
40 | return std::move(m_polylines);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/geometry/filter/sorter.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry::filter
6 | {
7 |
8 | /** @brief Sort polyline by length.
9 | */
10 | class Sorter
11 | {
12 | private:
13 | Polyline::List m_polylines;
14 |
15 | public:
16 | explicit Sorter(Polyline::List &&polylines);
17 |
18 | Polyline::List &&polylines();
19 | };
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/geometry/line.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace geometry
4 | {
5 |
6 | Line::Line(const QVector2D &start, const QVector2D &end)
7 | :m_start(start),
8 | m_end(end)
9 | {
10 | }
11 |
12 | const QVector2D &Line::start() const
13 | {
14 | return m_start;
15 | }
16 |
17 | const QVector2D &Line::end() const
18 | {
19 | return m_end;
20 | }
21 |
22 | bool Line::lengthNonZero() const
23 | {
24 | return (m_start != m_end);
25 | }
26 |
27 | float Line::length() const
28 | {
29 | return m_start.distanceToPoint(m_end);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/geometry/line.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry
6 | {
7 |
8 | class Line
9 | {
10 | private:
11 | QVector2D m_start;
12 | QVector2D m_end;
13 |
14 | public:
15 | explicit Line(const QVector2D &start, const QVector2D& end);
16 |
17 | const QVector2D &start() const;
18 | const QVector2D &end() const;
19 |
20 | bool lengthNonZero() const;
21 | float length() const;
22 | };
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/geometry/pocketer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace geometry
8 | {
9 |
10 | class Pocketer
11 | {
12 | private:
13 | const Polyline& m_border;
14 | const Orientation m_borderOrientation;
15 | const Polyline::ListCPtr &m_islands;
16 | const float m_margin;
17 | const float m_minimumPolylineLength;
18 | cavc::ParallelOffsetIslands m_offseter;
19 |
20 | Polyline::List m_polylines;
21 | Polyline::List m_ccwPolylines;
22 | Polyline::List m_cwPolylines;
23 |
24 | static bool isCapable(const Polyline &polyline);
25 | bool isBorderAndInslandsCapable() const;
26 | static cavc::OffsetLoop polylineToLoop(const Polyline& polyline, Orientation expectedOrientation);
27 | static cavc::OffsetLoop polylineToLoop(const Polyline& polyline, bool inverse);
28 | static Polyline loopToPolyline(const cavc::OffsetLoop &loop);
29 | static Polyline::List loopsToPolylines(const std::vector> &loops);
30 | static bool canContinueOffsetting(const cavc::OffsetLoopSet &loopSet);
31 | void pruneSingularities(std::vector> &loops) const;
32 | cavc::OffsetLoopSet baseLoopSet() const;
33 |
34 | cavc::OffsetLoopSet computeNextLoopSet(const cavc::OffsetLoopSet &loopSet);
35 | void appendLoopSetPolylines(const cavc::OffsetLoopSet &loopSet);
36 | void appendPolylines(const Polyline::List &polylines, bool inverse);
37 | void ensurePolylinesOrientationSameAsBorder();
38 |
39 | public:
40 | explicit Pocketer(const Polyline &border, const Polyline::ListCPtr &islands, float margin, float minimumPolylineLength);
41 |
42 | Orientation borderOrientation() const;
43 | Polyline::List &&polylines();
44 | };
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/geometry/polyline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #include
11 |
12 | namespace geometry
13 | {
14 |
15 | class Polyline : public common::Aggregable
16 | {
17 | friend serializer::Access;
18 | friend class Pocketer;
19 |
20 | private:
21 | Bulge::List m_bulges;
22 |
23 | explicit Polyline(const cavc::Polyline &polyline);
24 | cavc::Polyline toCavc() const;
25 | cavc::Polyline toCavc(Orientation expectedOrientation) const;
26 | cavc::Polyline toCavc(bool inverse) const;
27 |
28 | public:
29 | explicit Polyline() = default;
30 | explicit Polyline(Bulge::List &&bulges);
31 |
32 | const QVector2D &start() const;
33 | QVector2D &start();
34 | const QVector2D &end() const;
35 | QVector2D &end();
36 |
37 | bool isClosed() const;
38 | bool isPoint() const;
39 | bool isLine() const;
40 |
41 | float length() const;
42 |
43 | Orientation orientation() const;
44 |
45 | Rect boundingRect() const;
46 |
47 | Polyline &invert();
48 | Polyline inverse() const;
49 |
50 | Polyline& operator+=(const Polyline &other);
51 |
52 | template
53 | void forEachBulge(Functor &&functor) const
54 | {
55 | for (const Bulge &bulge : m_bulges) {
56 | functor(bulge);
57 | }
58 | }
59 |
60 | template
61 | void transformBulge(Functor &&functor)
62 | {
63 | for (Bulge &bulge : m_bulges) {
64 | functor(bulge);
65 | }
66 | }
67 |
68 | Polyline::List offsetted(float margin) const;
69 |
70 | void transform(const QTransform &matrix);
71 |
72 | bool operator==(const Polyline &other) const;
73 |
74 | bool equals(const Polyline &other, bool inverse) const;
75 | };
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/geometry/quadraticspline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace geometry
6 | {
7 |
8 | class QuadraticSpline : public Spline
9 | {
10 | private:
11 | Point2DList convertClosedToQuadraticBezierPoints() const;
12 | Point2DList convertOpenedToQuadraticBezierPoints() const;
13 |
14 | Bezier::List pointsToBeziers(const Point2DList &bezierPoints) const;
15 |
16 | public:
17 | explicit QuadraticSpline(Point2DList &&points, bool closed);
18 |
19 | Bezier::List toBeziers() const;
20 | };
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/geometry/rect.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace geometry
4 | {
5 |
6 | QVector2D minVect(const QVector2D &v1, const QVector2D &v2)
7 | {
8 | return {std::min(v1.x(), v2.x()), std::min(v1.y(), v2.y())};
9 | }
10 |
11 | QVector2D maxVect(const QVector2D &v1, const QVector2D &v2)
12 | {
13 | return {std::max(v1.x(), v2.x()), std::max(v1.y(), v2.y())};
14 | }
15 |
16 | Rect::Rect(const QVector2D &v)
17 | :m_min(v),
18 | m_max(v)
19 | {
20 | }
21 |
22 | Rect::Rect(const QVector2D &v1, const QVector2D& v2)
23 | :m_min(minVect(v1, v2)),
24 | m_max(maxVect(v1, v2))
25 | {
26 | }
27 |
28 | const QVector2D &Rect::min() const
29 | {
30 | return m_min;
31 | }
32 |
33 | const QVector2D &Rect::max() const
34 | {
35 | return m_max;
36 | }
37 |
38 | QVector2D Rect::bottomLeft() const
39 | {
40 | return m_min;
41 | }
42 |
43 | QVector2D Rect::topLeft() const
44 | {
45 | return QVector2D(m_min.x(), m_max.y());
46 | }
47 | QVector2D Rect::topRight() const
48 | {
49 | return m_max;
50 | }
51 | QVector2D Rect::bottomRight() const
52 | {
53 | return QVector2D(m_max.x(), m_min.y());
54 | }
55 |
56 | QRectF Rect::toQt() const
57 | {
58 | const QPointF topLeft(m_min.x(), m_max.y());
59 | const QPointF bottomRight(m_max.x(), m_min.y());
60 |
61 | return QRectF(topLeft, bottomRight);
62 | }
63 |
64 | Rect Rect::operator|(const Rect& other) const
65 | {
66 | return Rect(minVect(min(), other.min()), maxVect(max(), other.max()));
67 | }
68 |
69 | Rect &Rect::operator|=(const Rect& other)
70 | {
71 | m_min = minVect(min(), other.min());
72 | m_max = maxVect(max(), other.max());
73 | return *this;
74 | }
75 |
76 | Rect Rect::operator+(const QVector2D &v)
77 | {
78 | Rect extendedRect;
79 | extendedRect.m_min = minVect(m_min, v);
80 | extendedRect.m_max = maxVect(m_max, v);
81 |
82 | return extendedRect;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/geometry/rect.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace geometry
7 | {
8 |
9 | class Rect
10 | {
11 | private:
12 | QVector2D m_min;
13 | QVector2D m_max;
14 |
15 | public:
16 | Rect() = default;
17 | explicit Rect(const QVector2D &v);
18 | explicit Rect(const QVector2D &v1, const QVector2D& v2);
19 |
20 | const QVector2D &min() const;
21 | const QVector2D &max() const;
22 |
23 | QVector2D bottomLeft() const;
24 | QVector2D topLeft() const;
25 | QVector2D topRight() const;
26 | QVector2D bottomRight() const;
27 |
28 | QRectF toQt() const;
29 |
30 | Rect operator|(const Rect& other) const;
31 | Rect &operator|=(const Rect& other);
32 | Rect operator+(const QVector2D &v);
33 | };
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/geometry/spline.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace geometry
4 | {
5 |
6 | const Point2DList& Spline::controlPoints() const
7 | {
8 | return m_controlPoints;
9 | }
10 |
11 | bool Spline::closed() const
12 | {
13 | return m_closed;
14 | }
15 |
16 | Spline::Spline(Point2DList &&points, bool closed)
17 | :m_controlPoints(points),
18 | m_closed(closed)
19 | {
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/geometry/spline.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace geometry
7 | {
8 |
9 | class Spline
10 | {
11 | private:
12 | Point2DList m_controlPoints;
13 | bool m_closed;
14 |
15 | protected:
16 | const Point2DList& controlPoints() const;
17 | bool closed() const;
18 |
19 | public:
20 | explicit Spline(Point2DList &&points, bool closed);
21 | };
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/importer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(dxf)
2 | add_subdirectory(dxfplot)
3 |
--------------------------------------------------------------------------------
/src/importer/dxf/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | entityimporter.cpp
3 | importer.cpp
4 | interface.cpp
5 | layer.cpp
6 |
7 | entityimporter.h
8 | importer.h
9 | interface.h
10 | utils.h
11 | layer.h
12 | )
13 |
14 | add_library(importer-dxf ${SRC})
15 |
--------------------------------------------------------------------------------
/src/importer/dxf/entityimporter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace importer::dxf
4 | {
5 |
6 | BaseEntityImporter::BaseEntityImporter(Layer& layer, const Settings& settings)
7 | :m_layer(layer),
8 | m_settings(settings)
9 | {
10 | }
11 |
12 | void BaseEntityImporter::addPolyline(const geometry::Polyline& polyline)
13 | {
14 | m_layer.addPolyline(polyline);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/importer/dxf/importer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include
7 |
8 | namespace importer::dxf
9 | {
10 |
11 | void Importer::addLayer(const DRW_Layer &layer)
12 | {
13 | if (layer.plotF) {
14 | const std::string &name = layer.name;
15 | m_nameToLayers.emplace(name, Layer(name));
16 | }
17 | }
18 |
19 | Importer::Importer(const std::string& filename, float splineToArcPrecision, float minimumSplineLength, float minimumArcLength)
20 | :m_entityImporterSettings({splineToArcPrecision, minimumSplineLength, minimumArcLength}),
21 | m_ignoreEntities(false)
22 | {
23 | Interface interface(*this);
24 |
25 | dxfRW rw(filename.c_str());
26 | if (!rw.read(&interface, false)) {
27 | throw common::FileCouldNotOpenException();
28 | }
29 | }
30 |
31 | Layer::List Importer::layers() const
32 | {
33 | Layer::List layers(m_nameToLayers.size());
34 | std::transform(m_nameToLayers.begin(), m_nameToLayers.end(), layers.begin(),
35 | [](const auto& pair){ return pair.second; });
36 |
37 | return layers;
38 | }
39 |
40 | void Importer::startBlock()
41 | {
42 | m_ignoreEntities = true;
43 | }
44 |
45 | void Importer::endBlock()
46 | {
47 | m_ignoreEntities = false;
48 | }
49 |
50 | template <>
51 | void Importer::processEntity(const DRW_Layer &layer)
52 | {
53 | addLayer(layer);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/importer/dxf/importer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | namespace importer::dxf
15 | {
16 |
17 | class Importer
18 | {
19 | private:
20 | const BaseEntityImporter::Settings m_entityImporterSettings;
21 |
22 | std::unordered_map m_nameToLayers;
23 | bool m_ignoreEntities;
24 |
25 | void addLayer(const DRW_Layer &layer);
26 |
27 | public:
28 | explicit Importer(const std::string &filename, float splineToArcPrecision, float minimumSplineLength, float minimumArcLength);
29 |
30 | Layer::List layers() const;
31 |
32 | template
33 | void processEntity(const Entity &entity)
34 | {
35 | if (!m_ignoreEntities) {
36 | auto it = m_nameToLayers.find(entity.layer);
37 | if (it != m_nameToLayers.end()) {
38 | Layer &layer = it->second;
39 |
40 | EntityImporter entityImporter(layer, m_entityImporterSettings);
41 | entityImporter(entity);
42 | }
43 | }
44 | }
45 |
46 | void startBlock();
47 | void endBlock();
48 | };
49 |
50 | template <>
51 | void Importer::processEntity(const DRW_Layer &layer);
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/importer/dxf/layer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace importer::dxf
4 | {
5 |
6 | Layer::Layer(const std::string& name)
7 | :m_name(name)
8 | {
9 | }
10 |
11 | void Layer::addPolyline(const geometry::Polyline& polyline)
12 | {
13 | m_polylines.push_back(polyline);
14 | }
15 |
16 | geometry::Polyline::List &&Layer::polylines()
17 | {
18 | return std::move(m_polylines);
19 | }
20 |
21 | const std::string& Layer::name() const
22 | {
23 | return m_name;
24 | }
25 |
26 | }
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/importer/dxf/layer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace importer::dxf
8 | {
9 |
10 | class Layer : public common::Aggregable
11 | {
12 | private:
13 | geometry::Polyline::List m_polylines;
14 | std::string m_name;
15 |
16 | public:
17 | Layer() = default;
18 |
19 | explicit Layer(const std::string& name);
20 |
21 | void addPolyline(const geometry::Polyline& polyline);
22 |
23 | geometry::Polyline::List &&polylines();
24 |
25 | const std::string& name() const;
26 | };
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/src/importer/dxf/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace importer::dxf
8 | {
9 |
10 | inline QVector2D toVector2D(const DRW_Coord &coord)
11 | {
12 | return QVector2D(coord.x, coord.y);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/importer/dxfplot/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | importer.cpp
3 |
4 | importer.h
5 | )
6 |
7 | add_library(importer-dxfplot ${SRC})
8 |
--------------------------------------------------------------------------------
/src/importer/dxfplot/importer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #include
11 |
12 | namespace importer::dxfplot
13 | {
14 |
15 | Importer::Importer(const config::Tools &tools, const config::Profiles &profiles)
16 | :m_tools(tools),
17 | m_profiles(profiles)
18 | {
19 | }
20 |
21 | model::Document::UPtr Importer::operator()(const std::string &fileName) const
22 | {
23 | std::ifstream input(fileName);
24 |
25 | return (*this)(input);
26 | }
27 |
28 | model::Document::UPtr Importer::operator()(std::istream& input) const
29 | {
30 | Archive archive(input);
31 |
32 | model::Task::UPtr task = std::make_unique();
33 | archive(cereal::make_nvp("task", *task));
34 |
35 | std::string profileName;
36 | archive(cereal::make_nvp("profile_name", profileName));
37 |
38 | std::string toolName;
39 | archive(cereal::make_nvp("tool_name", toolName));
40 |
41 | const config::Tools::Tool *tool = m_tools.get(toolName);
42 | const config::Profiles::Profile *profile = m_profiles.get(profileName);
43 |
44 | if (!tool) {
45 | throw common::ImportCouldNotFindToolConfigException();
46 | }
47 | if (!profile) {
48 | throw common::ImportCouldNotFindProfileConfigException();
49 | }
50 |
51 | return std::make_unique(std::move(task), *tool, *profile);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/importer/dxfplot/importer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include // TODO
8 |
9 | namespace importer::dxfplot
10 | {
11 |
12 | class Importer
13 | {
14 | private:
15 | using Archive = cereal::JSONInputArchive;
16 |
17 | const config::Tools &m_tools;
18 | const config::Profiles &m_profiles;
19 |
20 | public:
21 | explicit Importer(const config::Tools &tools, const config::Profiles &profiles);
22 |
23 | model::Document::UPtr operator()(const std::string &fileName) const;
24 | model::Document::UPtr operator()(std::istream& input) const;
25 | };
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/model/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(SRC
2 | application.cpp
3 | document.cpp
4 | layer.cpp
5 | offsettedpath.cpp
6 | path.cpp
7 | pathsettings.cpp
8 | pathgroupsettings.cpp
9 | renderable.cpp
10 | simulation.cpp
11 | task.cpp
12 |
13 | application.h
14 | document.h
15 | layer.h
16 | path.h
17 | offsettedpath.h
18 | pathsettings.h
19 | pathgroupsettings.h
20 | renderable.h
21 | simulation.h
22 | task.h
23 | documentmodelobserver.h
24 | )
25 |
26 | add_library(model ${SRC})
27 | add_dependencies(model generate-config)
28 | add_coverage(model)
29 |
--------------------------------------------------------------------------------
/src/model/document.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace model
4 | {
5 |
6 | Document::Document(Task::UPtr&& task, const config::Tools::Tool &toolConfig, const config::Profiles::Profile &profileConfig)
7 | :m_task(std::move(task)),
8 | m_toolConfig(&toolConfig),
9 | m_profileConfig(&profileConfig)
10 | {
11 |
12 | }
13 |
14 | Task &Document::task()
15 | {
16 | return *m_task;
17 | }
18 |
19 | const Task &Document::task() const
20 | {
21 | return *m_task;
22 | }
23 |
24 | const config::Tools::Tool &Document::toolConfig() const
25 | {
26 | return *m_toolConfig;
27 | }
28 |
29 | const config::Profiles::Profile &Document::profileConfig() const
30 | {
31 | return *m_profileConfig;
32 | }
33 |
34 | void Document::setToolConfig(const config::Tools::Tool &tool)
35 | {
36 | m_toolConfig = &tool;
37 | emit toolConfigChanged(tool);
38 | }
39 |
40 | void Document::setProfileConfig(const config::Profiles::Profile &profile)
41 | {
42 | m_profileConfig = &profile;
43 | emit profileConfigChanged(profile);
44 | }
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/model/document.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace model
7 | {
8 |
9 | class Document : public QObject, public common::Aggregable
10 | {
11 | Q_OBJECT;
12 |
13 | private:
14 | Task::UPtr m_task;
15 | const config::Tools::Tool *m_toolConfig;
16 | const config::Profiles::Profile *m_profileConfig;
17 |
18 | public:
19 | explicit Document(Task::UPtr&& task, const config::Tools::Tool &toolConfig, const config::Profiles::Profile &profileConfig);
20 | Document() = default;
21 |
22 | Task& task();
23 | const Task& task() const;
24 |
25 | const config::Tools::Tool &toolConfig() const;
26 | const config::Profiles::Profile &profileConfig() const;
27 | void setToolConfig(const config::Tools::Tool &tool);
28 | void setProfileConfig(const config::Profiles::Profile &profile);
29 |
30 | Q_SIGNALS:
31 | void toolConfigChanged(const config::Tools::Tool &tool);
32 | void profileConfigChanged(const config::Profiles::Profile &profile);
33 | };
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/model/documentmodelobserver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace model
8 | {
9 |
10 | class Document;
11 |
12 | /** @brief A observer on Document changes
13 | * e.g when a file is opened the document is changed and this observers is notified.
14 | * Function @ref documentChanged is called at every changes
15 | */
16 | template
17 | class DocumentModelObserver : public QtBaseObject
18 | {
19 | private:
20 | /// Current document.
21 | Document *m_document;
22 |
23 | /** Function called when the document in the application had changed,
24 | * m_document is ensured to be valid before.
25 | * Before the first call to this function, m_document is inaccesible.
26 | */
27 | virtual void documentChanged() = 0;
28 |
29 | protected:
30 | Document *document() const
31 | {
32 | return m_document;
33 | }
34 |
35 | Task &task()
36 | {
37 | assert(m_document);
38 | return m_document->task();
39 | }
40 |
41 | private Q_SLOTS:
42 | void internalDocumentChanged(Document *newDocument)
43 | {
44 | m_document = newDocument;
45 | assert(m_document);
46 | documentChanged();
47 | }
48 |
49 | public:
50 | explicit DocumentModelObserver(Application &app)
51 | :m_document(nullptr)
52 | {
53 | QObject::connect(&app, &Application::documentChanged, this, &DocumentModelObserver::internalDocumentChanged);
54 | }
55 |
56 | };
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/src/model/layer.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace model
4 | {
5 |
6 | void Layer::assignSelfToChildren()
7 | {
8 | for (Path::UPtr &child : m_children) {
9 | child->setLayer(*this);
10 | }
11 | }
12 |
13 | Layer::Layer(const std::string &name, Path::ListUPtr &&children)
14 | :Renderable(name),
15 | m_children(std::move(children))
16 | {
17 | assignSelfToChildren();
18 | }
19 |
20 | int Layer::childrenCount() const
21 | {
22 | return m_children.size();
23 | }
24 |
25 |
26 | Path& Layer::childrenAt(int index)
27 | {
28 | assert(0 <= index && index < childrenCount());
29 | return *m_children[index];
30 | }
31 |
32 | const Path& Layer::childrenAt(int index) const
33 | {
34 | assert(0 <= index && index < childrenCount());
35 | return *m_children[index];
36 | }
37 |
38 | int Layer::childIndexFor(const Path& child) const
39 | {
40 | const Path::ListUPtr::const_iterator it = std::find_if(m_children.cbegin(), m_children.cend(), [&child](const Path::UPtr &ptr){ return ptr.get() == &child; });
41 |
42 | if (it == m_children.cend()) {
43 | return -1;
44 | }
45 |
46 | return std::distance(m_children.cbegin(), it);
47 | }
48 |
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/model/layer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | namespace model
8 | {
9 |
10 | class Layer : public Renderable, public common::Aggregable
11 | {
12 | Q_OBJECT;
13 |
14 | friend serializer::Access;
15 |
16 | private:
17 | Path::ListUPtr m_children;
18 |
19 | void assignSelfToChildren();
20 |
21 | public:
22 | explicit Layer(const std::string &name, Path::ListUPtr &&children);
23 | explicit Layer() = default;
24 |
25 | int childrenCount() const;
26 | Path& childrenAt(int index);
27 | const Path& childrenAt(int index) const;
28 | int childIndexFor(const Path& child) const;
29 |
30 | template
31 | void forEachChild(Functor &&functor)
32 | {
33 | for (Path::UPtr &child : m_children) {
34 | functor(*child);
35 | }
36 | }
37 | };
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/model/offsettedpath.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace model
4 | {
5 |
6 | OffsettedPath::OffsettedPath(geometry::Polyline::List &&offsettedPolylines, Direction direction)
7 | :m_polylines(offsettedPolylines),
8 | m_direction(direction)
9 | {
10 | }
11 |
12 | const geometry::Polyline::List &OffsettedPath::polylines() const
13 | {
14 | return m_polylines;
15 | }
16 |
17 | geometry::CuttingDirection OffsettedPath::cuttingDirection() const
18 | {
19 | static const geometry::CuttingDirection offsetDirectionToCuttingDirection[] = {
20 | geometry::CuttingDirection::FORWARD, // OffsettedPath::Direction::LEFT
21 | geometry::CuttingDirection::BACKWARD // OffsettedPath::Direction::RIGHT
22 | };
23 |
24 | return offsetDirectionToCuttingDirection[static_cast(m_direction)];
25 | }
26 |
27 | void OffsettedPath::transform(const QTransform &matrix)
28 | {
29 | for (geometry::Polyline &polyline : m_polylines) {
30 | polyline.transform(matrix);
31 | }
32 |
33 | emit polylinesTransformed();
34 | }
35 |
36 | geometry::Rect OffsettedPath::boundingRect() const
37 | {
38 | geometry::Polyline::List::const_iterator it = m_polylines.begin();
39 | const geometry::Rect firstBoundingRest = (it++)->boundingRect();
40 |
41 | return std::transform_reduce(it, m_polylines.end(), firstBoundingRest, std::bit_or(),
42 | [](const geometry::Polyline& polyline){
43 | return polyline.boundingRect();
44 | });
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/model/offsettedpath.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | namespace model
13 | {
14 |
15 | class Layer;
16 |
17 | class OffsettedPath : public QObject
18 | {
19 | Q_OBJECT
20 |
21 | friend serializer::Access;
22 |
23 | public:
24 | enum class Direction
25 | {
26 | LEFT = 0,
27 | RIGHT
28 | };
29 |
30 | private:
31 | geometry::Polyline::List m_polylines;
32 | Direction m_direction;
33 |
34 | public:
35 | explicit OffsettedPath(geometry::Polyline::List &&offsettedPolylines, Direction direction);
36 | explicit OffsettedPath() = default;
37 |
38 | const geometry::Polyline::List &polylines() const;
39 | geometry::CuttingDirection cuttingDirection() const;
40 |
41 | void transform(const QTransform &matrix);
42 |
43 | geometry::Rect boundingRect() const;
44 |
45 | Q_SIGNALS:
46 | void polylinesTransformed();
47 | };
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/model/path.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | namespace model
16 | {
17 |
18 | class Layer;
19 |
20 | class Path : public Renderable, public common::Aggregable
21 | {
22 | Q_OBJECT;
23 |
24 | friend serializer::Access;
25 |
26 | private:
27 | geometry::Polyline m_basePolyline;
28 | std::unique_ptr m_offsettedPath;
29 | PathSettings m_settings;
30 | Layer *m_layer;
31 | bool m_globallyVisible;
32 |
33 | void updateGlobalVisibility();
34 |
35 | public:
36 | explicit Path(geometry::Polyline &&basePolyline, const std::string &name, const PathSettings& settings);
37 | explicit Path() = default;
38 |
39 | static ListUPtr FromPolylines(geometry::Polyline::List &&polylines, const PathSettings &settings, const std::string &layerName);
40 |
41 | Layer &layer();
42 | const Layer &layer() const;
43 | void setLayer(Layer &layer);
44 |
45 | const geometry::Polyline &basePolyline() const;
46 | geometry::Polyline::List finalPolylines() const;
47 |
48 | model::OffsettedPath *offsettedPath() const;
49 | void offset(float margin, float minimumPolylineLength, float minimumArcLength);
50 | void resetOffset();
51 | void pocket(const Path::ListCPtr &islands, float scaledRadius, float minimumPolylineLength, float minimumArcLength);
52 |
53 | void transform(const QTransform &matrix);
54 |
55 | geometry::Rect boundingRect() const;
56 |
57 | bool isPoint() const;
58 |
59 | const PathSettings &settings() const;
60 | PathSettings &settings();
61 |
62 | geometry::CuttingDirection cuttingDirection() const;
63 |
64 | bool globallyVisible() const;
65 |
66 | Q_SIGNALS:
67 | void globalVisibilityChanged(bool globallyVisible);
68 | void offsettedPathChanged();
69 | void basePolylineTransformed();
70 | };
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/model/pathgroupsettings.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include // TODO
4 |
5 | namespace model
6 | {
7 |
8 | PathGroupSettings::PathGroupSettings(const Task &task)
9 | :m_task(task)
10 | {
11 | }
12 |
13 | std::optional PathGroupSettings::planeFeedRate() const
14 | {
15 | return valueIfAllEqual(&PathSettings::planeFeedRate);
16 | }
17 |
18 | void PathGroupSettings::setPlaneFeedRate(float planeFeedRate)
19 | {
20 | setValue(&PathSettings::setPlaneFeedRate, planeFeedRate);
21 | }
22 |
23 | std::optional PathGroupSettings::depthFeedRate() const
24 | {
25 | return valueIfAllEqual(&PathSettings::depthFeedRate);
26 | }
27 |
28 | void PathGroupSettings::setDepthFeedRate(float depthFeedRate)
29 | {
30 | setValue(&PathSettings::setDepthFeedRate, depthFeedRate);
31 | }
32 |
33 | std::optional PathGroupSettings::intensity() const
34 | {
35 | return valueIfAllEqual(&PathSettings::intensity);
36 | }
37 |
38 | void PathGroupSettings::setIntensity(float intensity)
39 | {
40 | setValue(&PathSettings::setIntensity, intensity);
41 | }
42 |
43 | std::optional PathGroupSettings::depth() const
44 | {
45 | return valueIfAllEqual(&PathSettings::depth);
46 | }
47 |
48 | void PathGroupSettings::setDepth(float depth)
49 | {
50 | setValue(&PathSettings::setDepth, depth);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/model/pathgroupsettings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include
10 |
11 | namespace model
12 | {
13 |
14 | class PathGroupSettings : public QObject
15 | {
16 | Q_OBJECT;
17 |
18 | private:
19 | const model::Task &m_task;
20 |
21 | /** Return value of a path settings property if all path have
22 | * the same value for the given property.
23 | *
24 | * @tparam T The returned value type
25 | * @tparam Getter The member function used to acces the poperty.
26 | */
27 | template ::Return>
28 | std::optional valueIfAllEqual(Getter &&getter) const
29 | {
30 | // Reference value of last path to compare with.
31 | Return lastValue;
32 | bool firstValue = true;
33 | bool allEqual = true;
34 |
35 | m_task.forEachSelectedPath([&lastValue, &firstValue, &allEqual, &getter](const model::Path &path){
36 | const Return &value = (path.settings().*getter)();
37 | if (!firstValue && lastValue != value) {
38 | allEqual = false;
39 | }
40 | firstValue = false;
41 | lastValue = value;
42 | });
43 |
44 | if (allEqual) {
45 | return std::make_optional(lastValue);
46 | }
47 | return std::nullopt;
48 | }
49 |
50 | template
51 | void setValue(Setter &&setter, T value)
52 | {
53 | m_task.forEachSelectedPath([value, &setter](model::Path &path){
54 | (path.settings().*(std::forward(setter)))(value);
55 | });
56 | }
57 |
58 | public:
59 | explicit PathGroupSettings(const Task &task);
60 |
61 | std::optional planeFeedRate() const;
62 | void setPlaneFeedRate(float planeFeedRate);
63 |
64 | std::optional depthFeedRate() const;
65 | void setDepthFeedRate(float depthFeedRate);
66 |
67 | std::optional intensity() const;
68 | void setIntensity(float intensity);
69 |
70 | std::optional depth() const;
71 | void setDepth(float depth);
72 | };
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/model/pathsettings.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace model
4 | {
5 |
6 | PathSettings::PathSettings(float planeFeedRate, float depthFeedRate, float intensity, float depth)
7 | :m_planeFeedRate(planeFeedRate),
8 | m_depthFeedRate(depthFeedRate),
9 | m_intensity(intensity),
10 | m_depth(depth)
11 | {
12 | }
13 |
14 | float PathSettings::planeFeedRate() const
15 | {
16 | return m_planeFeedRate;
17 | }
18 |
19 | void PathSettings::setPlaneFeedRate(float planeFeedRate)
20 | {
21 | m_planeFeedRate = planeFeedRate;
22 | }
23 |
24 | float PathSettings::depthFeedRate() const
25 | {
26 | return m_depthFeedRate;
27 | }
28 |
29 | void PathSettings::setDepthFeedRate(float depthFeedRate)
30 | {
31 | m_depthFeedRate = depthFeedRate;
32 | }
33 |
34 | float PathSettings::intensity() const
35 | {
36 | return m_intensity;
37 | }
38 |
39 | void PathSettings::setIntensity(float intensity)
40 | {
41 | m_intensity = intensity;
42 | }
43 |
44 | float PathSettings::depth() const
45 | {
46 | return m_depth;
47 | }
48 |
49 | void PathSettings::setDepth(float depth)
50 | {
51 | m_depth = depth;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/model/pathsettings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace model
6 | {
7 |
8 | class PathSettings
9 | {
10 | friend serializer::Access;
11 |
12 | private:
13 | float m_planeFeedRate;
14 | float m_depthFeedRate;
15 | float m_intensity;
16 | float m_depth;
17 |
18 | public:
19 | explicit PathSettings() = default;
20 | explicit PathSettings(float planeFeedRate, float depthFeedRate, float intensity, float depth);
21 |
22 | float planeFeedRate() const;
23 | void setPlaneFeedRate(float planeFeedRate);
24 |
25 | float depthFeedRate() const;
26 | void setDepthFeedRate(float depthFeedRate);
27 |
28 | float intensity() const;
29 | void setIntensity(float intensity);
30 |
31 | float depth() const;
32 | void setDepth(float depth);
33 | };
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/model/renderable.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | namespace model
4 | {
5 |
6 | Renderable::Renderable(const std::string &name)
7 | :m_name(name),
8 | m_selected(false),
9 | m_visible(true)
10 | {
11 | }
12 |
13 | const std::string &Renderable::name() const
14 | {
15 | return m_name;
16 | }
17 |
18 | bool Renderable::visible() const
19 | {
20 | return m_visible;
21 | }
22 |
23 | void Renderable::setVisible(bool visible)
24 | {
25 | if (m_visible != visible) {
26 | m_visible = visible;
27 |
28 | emit visibilityChanged(m_visible);
29 | }
30 | }
31 |
32 | void Renderable::toggleVisible()
33 | {
34 | setVisible(!m_visible);
35 | }
36 |
37 | bool Renderable::selected() const
38 | {
39 | return m_selected;
40 | }
41 |
42 | void Renderable::setSelected(bool selected)
43 | {
44 | if (m_selected != selected) {
45 | m_selected = selected;
46 |
47 | emit selectedChanged(m_selected);
48 | }
49 | }
50 |
51 | void Renderable::toggleSelect()
52 | {
53 | setSelected(!m_selected);
54 | }
55 |
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/src/model/renderable.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include