From 4cacf40dcf1f921dfc7ba695856c3104ee89f117 Mon Sep 17 00:00:00 2001 From: Willem Sonke Date: Fri, 16 Aug 2024 17:54:52 +0200 Subject: [PATCH 1/4] Implement arc rendering in the GeometryWidget --- cartocrow/renderer/geometry_widget.cpp | 23 +++++++++++++++ cartocrow/renderer/render_path.cpp | 4 +++ cartocrow/renderer/render_path.h | 8 ++++- .../render_path_demo/render_path_demo.cpp | 29 ++++++++++++++----- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/cartocrow/renderer/geometry_widget.cpp b/cartocrow/renderer/geometry_widget.cpp index d31b5a2d0..a23823cfa 100644 --- a/cartocrow/renderer/geometry_widget.cpp +++ b/cartocrow/renderer/geometry_widget.cpp @@ -579,10 +579,33 @@ void GeometryWidget::draw(const RenderPath& p) { Point to = std::get(c).m_to; verticesToDraw.push_back(to); path.moveTo(convertPoint(to)); + } else if (std::holds_alternative(c)) { Point to = std::get(c).m_to; verticesToDraw.push_back(to); path.lineTo(convertPoint(std::get(c).m_to)); + + } else if (std::holds_alternative(c)) { + Point from = inverseConvertPoint(path.currentPosition()); + Point center = std::get(c).m_center; + Point to = std::get(c).m_to; + bool clockwise = std::get(c).m_clockwise; + verticesToDraw.push_back(to); + + double radius = sqrt((center - to).squared_length()); + Vector diagonal(radius, radius); + QRectF bounds(convertPoint(center - diagonal), convertPoint(center + diagonal)); + double startAngle = atan2((center - from).y(), (from - center).x()) * (180 / M_PI); + double endAngle = atan2((center - to).y(), (to - center).x()) * (180 / M_PI); + double sweepLength = endAngle - startAngle; + if (clockwise && sweepLength < 0) { + sweepLength += 360; + } + if (!clockwise && sweepLength > 0) { + sweepLength -= 360; + } + path.arcTo(bounds, startAngle, sweepLength); + } else if (std::holds_alternative(c)) { path.closeSubpath(); } diff --git a/cartocrow/renderer/render_path.cpp b/cartocrow/renderer/render_path.cpp index c59b2642e..03c69c2dc 100644 --- a/cartocrow/renderer/render_path.cpp +++ b/cartocrow/renderer/render_path.cpp @@ -33,6 +33,10 @@ void RenderPath::lineTo(Point to) { m_commands.push_back(LineTo{to}); } +void RenderPath::arcTo(Point center, bool clockwise, Point to) { + m_commands.push_back(ArcTo{center, clockwise, to}); +} + void RenderPath::close() { m_commands.push_back(Close{}); } diff --git a/cartocrow/renderer/render_path.h b/cartocrow/renderer/render_path.h index e3322e1e2..4178ba83e 100644 --- a/cartocrow/renderer/render_path.h +++ b/cartocrow/renderer/render_path.h @@ -35,13 +35,19 @@ class RenderPath { struct LineTo { Point m_to; }; + struct ArcTo { + Point m_center; + bool m_clockwise; + Point m_to; + }; struct Close {}; - using Command = std::variant; + using Command = std::variant; const std::vector& commands() const; void moveTo(Point to); void lineTo(Point to); + void arcTo(Point center, bool clockwise, Point to); void close(); private: diff --git a/demos/renderer/render_path_demo/render_path_demo.cpp b/demos/renderer/render_path_demo/render_path_demo.cpp index 877040f1d..046eae2c8 100644 --- a/demos/renderer/render_path_demo/render_path_demo.cpp +++ b/demos/renderer/render_path_demo/render_path_demo.cpp @@ -34,15 +34,30 @@ void DemoPainting::paint(GeometryRenderer& renderer) const { renderer.setFill(Color{120, 170, 240}); renderer.setMode(GeometryRenderer::DrawMode::fill | GeometryRenderer::DrawMode::stroke); - // construct a RenderPath + // construct a RenderPath with three subpaths RenderPath path; - path.moveTo(Point(0, 0)); - path.lineTo(Point(50, 50)); - path.lineTo(Point(70, -40)); + + path.moveTo(Point(-150, -50)); + for (int i = 0; i < 4; i++) { + double alpha = i * 2 * M_PI / 4; + path.arcTo(Point(-200 + 100 * cos(alpha), 100 * sin(alpha)), true, + Point(-200 + 50 * sqrt(2) * cos(alpha + M_PI / 4), + 50 * sqrt(2) * sin(alpha + M_PI / 4))); + } + + path.moveTo(Point(-30, 0)); + path.lineTo(Point(20, 50)); + path.lineTo(Point(40, -40)); + path.close(); + + path.moveTo(Point(225, -25)); + for (int i = 0; i < 4; i++) { + double alpha = i * 2 * M_PI / 4; + path.arcTo(Point(200 + 25 * cos(alpha), 25 * sin(alpha)), false, + Point(200 + 25 * sqrt(2) * cos(alpha + M_PI / 4), + 25 * sqrt(2) * sin(alpha + M_PI / 4))); + } path.close(); - path.moveTo(Point(100, 0)); - path.lineTo(Point(120, -50)); - path.lineTo(Point(150, 30)); // draw various shapes renderer.draw(path); From d0cec6b2722019cd3cf45f4dff31cf95917bf7fb Mon Sep 17 00:00:00 2001 From: Willem Sonke Date: Fri, 16 Aug 2024 18:22:12 +0200 Subject: [PATCH 2/4] Tidy up the GeometryWidget arc drawing code --- cartocrow/renderer/geometry_widget.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cartocrow/renderer/geometry_widget.cpp b/cartocrow/renderer/geometry_widget.cpp index a23823cfa..78b47b449 100644 --- a/cartocrow/renderer/geometry_widget.cpp +++ b/cartocrow/renderer/geometry_widget.cpp @@ -595,16 +595,19 @@ void GeometryWidget::draw(const RenderPath& p) { double radius = sqrt((center - to).squared_length()); Vector diagonal(radius, radius); QRectF bounds(convertPoint(center - diagonal), convertPoint(center + diagonal)); - double startAngle = atan2((center - from).y(), (from - center).x()) * (180 / M_PI); - double endAngle = atan2((center - to).y(), (to - center).x()) * (180 / M_PI); + + double startAngle = atan2((from - center).y(), (from - center).x()) * (180 / M_PI); + double endAngle = atan2((to - center).y(), (to - center).x()) * (180 / M_PI); double sweepLength = endAngle - startAngle; - if (clockwise && sweepLength < 0) { - sweepLength += 360; + if (!clockwise && sweepLength < 0) { + sweepLength += 360; // counter-clockwise -> positive sweepLength } - if (!clockwise && sweepLength > 0) { - sweepLength -= 360; + if (clockwise && sweepLength > 0) { + sweepLength -= 360; // clockwise -> negative sweepLength } - path.arcTo(bounds, startAngle, sweepLength); + // the angles are negative because the y-axis is pointing up here + // instead of down + path.arcTo(bounds, -startAngle, -sweepLength); } else if (std::holds_alternative(c)) { path.closeSubpath(); From 354fe32434a6e7753319e227199572052836fb42 Mon Sep 17 00:00:00 2001 From: Willem Sonke Date: Fri, 16 Aug 2024 18:31:50 +0200 Subject: [PATCH 3/4] Implement arc rendering in the IpeRenderer --- cartocrow/renderer/ipe_renderer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cartocrow/renderer/ipe_renderer.cpp b/cartocrow/renderer/ipe_renderer.cpp index 093685f69..c4f3ee3ea 100644 --- a/cartocrow/renderer/ipe_renderer.cpp +++ b/cartocrow/renderer/ipe_renderer.cpp @@ -212,6 +212,18 @@ void IpeRenderer::draw(const RenderPath& p) { verticesToDraw.push_back(to); curve->appendSegment(ipe::Vector(from.x(), from.y()), ipe::Vector(to.x(), to.y())); from = to; + + } else if (std::holds_alternative(c)) { + Point center = std::get(c).m_center; + Point to = std::get(c).m_to; + bool clockwise = std::get(c).m_clockwise; + verticesToDraw.push_back(to); + + double radius = sqrt((center - to).squared_length()); + ipe::Matrix matrix(radius, 0, 0, clockwise ? -radius : radius, center.x(), center.y()); + curve->appendArc(matrix, ipe::Vector(from.x(), from.y()), ipe::Vector(to.x(), to.y())); + from = to; + } else if (std::holds_alternative(c)) { curve->setClosed(true); } From 4511f0146637b3fd6e798e2cb4b3000ae44753ee Mon Sep 17 00:00:00 2001 From: Willem Sonke Date: Mon, 19 Aug 2024 13:09:44 +0200 Subject: [PATCH 4/4] Remove -j4 from the CI builds --- .github/workflows/build-ubuntu-clang++-14.yml | 2 +- .github/workflows/build-ubuntu-g++-11.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-ubuntu-clang++-14.yml b/.github/workflows/build-ubuntu-clang++-14.yml index 31ed7ac5a..d536163cf 100644 --- a/.github/workflows/build-ubuntu-clang++-14.yml +++ b/.github/workflows/build-ubuntu-clang++-14.yml @@ -14,6 +14,6 @@ jobs: - name: CMake run: cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -S . -B build-clang - name: Build - run: cmake --build build-clang -j4 + run: cmake --build build-clang - name: Test run: build-clang/test/cartocrow_test diff --git a/.github/workflows/build-ubuntu-g++-11.yml b/.github/workflows/build-ubuntu-g++-11.yml index 6065e8080..c81ef9736 100644 --- a/.github/workflows/build-ubuntu-g++-11.yml +++ b/.github/workflows/build-ubuntu-g++-11.yml @@ -14,6 +14,6 @@ jobs: - name: CMake run: cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=Release -S . -B build - name: Build - run: cmake --build build -j4 + run: cmake --build build - name: Test run: build/test/cartocrow_test