Skip to content

Commit

Permalink
Merge pull request #43 from tue-alga/render-path-arcs
Browse files Browse the repository at this point in the history
Implement arc rendering
  • Loading branch information
Willem3141 authored Aug 19, 2024
2 parents 2997b6d + 4511f01 commit 0f699d5
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-ubuntu-clang++-14.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion .github/workflows/build-ubuntu-g++-11.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 26 additions & 0 deletions cartocrow/renderer/geometry_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,10 +579,36 @@ void GeometryWidget::draw(const RenderPath& p) {
Point<Inexact> to = std::get<RenderPath::MoveTo>(c).m_to;
verticesToDraw.push_back(to);
path.moveTo(convertPoint(to));

} else if (std::holds_alternative<RenderPath::LineTo>(c)) {
Point<Inexact> to = std::get<RenderPath::LineTo>(c).m_to;
verticesToDraw.push_back(to);
path.lineTo(convertPoint(std::get<RenderPath::LineTo>(c).m_to));

} else if (std::holds_alternative<RenderPath::ArcTo>(c)) {
Point<Inexact> from = inverseConvertPoint(path.currentPosition());
Point<Inexact> center = std::get<RenderPath::ArcTo>(c).m_center;
Point<Inexact> to = std::get<RenderPath::ArcTo>(c).m_to;
bool clockwise = std::get<RenderPath::ArcTo>(c).m_clockwise;
verticesToDraw.push_back(to);

double radius = sqrt((center - to).squared_length());
Vector<Inexact> diagonal(radius, radius);
QRectF bounds(convertPoint(center - diagonal), convertPoint(center + diagonal));

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; // counter-clockwise -> positive sweepLength
}
if (clockwise && sweepLength > 0) {
sweepLength -= 360; // clockwise -> negative 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<RenderPath::Close>(c)) {
path.closeSubpath();
}
Expand Down
12 changes: 12 additions & 0 deletions cartocrow/renderer/ipe_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<RenderPath::ArcTo>(c)) {
Point<Inexact> center = std::get<RenderPath::ArcTo>(c).m_center;
Point<Inexact> to = std::get<RenderPath::ArcTo>(c).m_to;
bool clockwise = std::get<RenderPath::ArcTo>(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<RenderPath::Close>(c)) {
curve->setClosed(true);
}
Expand Down
4 changes: 4 additions & 0 deletions cartocrow/renderer/render_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ void RenderPath::lineTo(Point<Inexact> to) {
m_commands.push_back(LineTo{to});
}

void RenderPath::arcTo(Point<Inexact> center, bool clockwise, Point<Inexact> to) {
m_commands.push_back(ArcTo{center, clockwise, to});
}

void RenderPath::close() {
m_commands.push_back(Close{});
}
Expand Down
8 changes: 7 additions & 1 deletion cartocrow/renderer/render_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ class RenderPath {
struct LineTo {
Point<Inexact> m_to;
};
struct ArcTo {
Point<Inexact> m_center;
bool m_clockwise;
Point<Inexact> m_to;
};
struct Close {};
using Command = std::variant<MoveTo, LineTo, Close>;
using Command = std::variant<MoveTo, LineTo, ArcTo, Close>;

const std::vector<Command>& commands() const;

void moveTo(Point<Inexact> to);
void lineTo(Point<Inexact> to);
void arcTo(Point<Inexact> center, bool clockwise, Point<Inexact> to);
void close();

private:
Expand Down
29 changes: 22 additions & 7 deletions demos/renderer/render_path_demo/render_path_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Inexact>(0, 0));
path.lineTo(Point<Inexact>(50, 50));
path.lineTo(Point<Inexact>(70, -40));

path.moveTo(Point<Inexact>(-150, -50));
for (int i = 0; i < 4; i++) {
double alpha = i * 2 * M_PI / 4;
path.arcTo(Point<Inexact>(-200 + 100 * cos(alpha), 100 * sin(alpha)), true,
Point<Inexact>(-200 + 50 * sqrt(2) * cos(alpha + M_PI / 4),
50 * sqrt(2) * sin(alpha + M_PI / 4)));
}

path.moveTo(Point<Inexact>(-30, 0));
path.lineTo(Point<Inexact>(20, 50));
path.lineTo(Point<Inexact>(40, -40));
path.close();

path.moveTo(Point<Inexact>(225, -25));
for (int i = 0; i < 4; i++) {
double alpha = i * 2 * M_PI / 4;
path.arcTo(Point<Inexact>(200 + 25 * cos(alpha), 25 * sin(alpha)), false,
Point<Inexact>(200 + 25 * sqrt(2) * cos(alpha + M_PI / 4),
25 * sqrt(2) * sin(alpha + M_PI / 4)));
}
path.close();
path.moveTo(Point<Inexact>(100, 0));
path.lineTo(Point<Inexact>(120, -50));
path.lineTo(Point<Inexact>(150, 30));

// draw various shapes
renderer.draw(path);
Expand Down

0 comments on commit 0f699d5

Please sign in to comment.