Skip to content

Commit

Permalink
allow drawing on marked radius
Browse files Browse the repository at this point in the history
  • Loading branch information
rolandlo committed Dec 17, 2022
1 parent 2b42732 commit 4a1a176
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 6 deletions.
48 changes: 46 additions & 2 deletions src/core/control/CompassController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ auto CompassController::posRelToSide(double x, double y) const -> utl::Point<dou
}

auto CompassController::isInsideGeometryTool(double x, double y, double border) const -> bool {
const auto p = posRelToSide(x, y);
const utl::Point<double> p = posRelToSide(x, y);
return std::hypot(p.x, p.y) <= geometryTool->getHeight() + border;
}

Expand All @@ -35,12 +35,21 @@ auto CompassController::getPointForAngle(double a) const -> utl::Point<double> {
return utl::Point<double>(x, y);
}

auto CompassController::getPointForRadius(double r) const -> utl::Point<double> {
cairo_matrix_t matrix = geometryTool->getMatrix();
double x = r;
double y = 0.;
cairo_matrix_transform_point(&matrix, &x, &y);

return utl::Point<double>(x, y);
}

void CompassController::createOutlineStroke(double a) {
if (!std::isnan(a)) {
angleMax = a;
angleMin = a;

const auto p = this->getPointForAngle(a);
const utl::Point<double> p = this->getPointForAngle(a);
initializeStroke();
stroke->addPoint(Point(p.x, p.y));
stroke->addPoint(Point(p.x, p.y)); // doubled point
Expand All @@ -50,6 +59,21 @@ void CompassController::createOutlineStroke(double a) {
}
}

void CompassController::createRadialStroke(double x) {
if (!std::isnan(x)) {
radiusMax = x;
radiusMin = x;

const utl::Point<double> p = posRelToSide(x, 0.);
initializeStroke();
stroke->addPoint(Point(p.x, p.y));
stroke->addPoint(Point(p.x, p.y)); // doubled point
geometryTool->notify();
} else {
g_warning("No valid radius from compass!");
}
}

void CompassController::updateOutlineStroke(double x) {
angleMax = std::max(this->angleMax, x);
angleMin = std::min(this->angleMin, x);
Expand All @@ -72,10 +96,30 @@ void CompassController::updateOutlineStroke(double x) {
geometryTool->notify();
}

void CompassController::updateRadialStroke(double x) {
radiusMax = std::max(this->radiusMax, x);
radiusMin = std::min(this->radiusMin, x);
stroke->deletePointsFrom(0);
const utl::Point<double> p1 = getPointForRadius(radiusMin);
const utl::Point<double> p2 = getPointForRadius(radiusMax);

stroke->addPoint(Point(p1.x, p1.y));
stroke->addPoint(Point(p2.x, p2.y));
geometryTool->notify();
}

void CompassController::finalizeOutlineStroke() {
angleMax = std::numeric_limits<double>::lowest();
angleMin = std::numeric_limits<double>::max();
addStrokeToLayer();
}

void CompassController::finalizeRadialStroke() {
radiusMax = std::numeric_limits<double>::lowest();
radiusMin = std::numeric_limits<double>::max();
addStrokeToLayer();
}

auto CompassController::existsOutlineStroke() -> bool { return angleMax != std::numeric_limits<double>::lowest(); }

auto CompassController::existsRadialStroke() -> bool { return radiusMax != std::numeric_limits<double>::lowest(); }
42 changes: 40 additions & 2 deletions src/core/control/CompassController.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,17 @@ class CompassController: public GeometryToolController {
bool isInsideGeometryTool(double x, double y, double border = 0.0) const override;

/**
* @brief the point (in document coordinates) for a given angle on the outline of the setsquare
* @brief the point (in document coordinates) for a given angle on the outline of the compass
* @param a the angle with respect to the distinguished compass axis of the point
*/
utl::Point<double> getPointForPos(double a) const;
utl::Point<double> getPointForAngle(double a) const;

/**
* @brief the point (in document coordinates) for a given radius on the marked radius of the compass
* @param r the x-coordinate with respect to a coordinate system, in which the positive x-axis
* coincides with the marked radius and the origin lies in the center of the compass
*/
utl::Point<double> getPointForRadius(double r) const;

/**
* @brief creates a stroke starting at the given angle of the outline of the compass
Expand All @@ -82,12 +89,43 @@ class CompassController: public GeometryToolController {
*/
void finalizeOutlineStroke();

/**
* @brief finishes the stroke aligned to the marked radius of the compass
*/
void finalizeRadialStroke();

/**
* @brief creates a stroke starting at the given point of the marked radius of the compass
* @param x the x-coordinate with respect to the marked radius
*/
void createRadialStroke(double x);

/**
* @brief updates the stroke near the marked radius of the compass
* @param x the x-coordinate with respect to the marked radius
*/
void updateRadialStroke(double x);

/**
* checks whether a stroke near the outline already exists
*/
bool existsOutlineStroke();

/**
* checks whether a radius already exists
*/
bool existsRadialStroke();

private:
/**
* @brief when a stroke near the radius with the measuring marks
* is drawn, the minimal and maximal radii are saved in
* the variables radiusMax and radiusMin
*
*/
double radiusMax = std::numeric_limits<double>::lowest();
double radiusMin = std::numeric_limits<double>::max();

/**
* @brief when a stroke near the outline of the compass is drawn, the minimal and maximal
* angles of the point to be drawn (with respect to an unrotated, and untranslated coordinate system)
Expand Down
14 changes: 12 additions & 2 deletions src/core/gui/inputdevices/CompassInputHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ CompassInputHandler::~CompassInputHandler() noexcept { this->unregisterFromPool(
auto CompassInputHandler::handlePointer(InputEvent const& event) -> bool {
const auto coords = getCoords(event);
CompassController* compassController = static_cast<CompassController*>(controller);
const auto p = compassController->posRelToSide(coords.x, coords.y);

const auto toolHandler = xournal->getControl()->getToolHandler();
switch (toolHandler->getToolType()) {
Expand All @@ -31,21 +32,27 @@ auto CompassInputHandler::handlePointer(InputEvent const& event) -> bool {
if (controller->isInsideGeometryTool(coords.x, coords.y, 0) &&
!controller->isInsideGeometryTool(coords.x, coords.y, -0.5)) {
// initialize range
const auto p = compassController->posRelToSide(coords.x, coords.y);
lastProj = std::atan2(-p.y, p.x);
compassController->createOutlineStroke(lastProj);
return true;
} else if (controller->isInsideGeometryTool(coords.x, coords.y, 0.) &&
std::abs(compassController->posRelToSide(coords.x, coords.y).y) <= 0.5 &&
std::abs(compassController->posRelToSide(coords.x, coords.y).x - 0.5 * height) <=
0.5 * height) {
compassController->createRadialStroke(std::hypot(p.x, p.y));
return true;
}
return false;
} else if (event.type == MOTION_EVENT) {
// update range and paint
if (compassController->existsOutlineStroke()) {
const auto p = compassController->posRelToSide(coords.x, coords.y);
auto proj = std::atan2(-p.y, p.x);
proj = lastProj + std::remainder(proj - lastProj, 2 * M_PI);
compassController->updateOutlineStroke(proj);
lastProj = proj;
return true;
} else if (compassController->existsRadialStroke()) {
compassController->updateRadialStroke(std::hypot(p.x, p.y));
}
return false;
} else if (event.type == BUTTON_RELEASE_EVENT) {
Expand All @@ -54,6 +61,9 @@ auto CompassInputHandler::handlePointer(InputEvent const& event) -> bool {
compassController->finalizeOutlineStroke();
lastProj = NAN;
return true;
} else if (compassController->existsRadialStroke()) {
compassController->finalizeRadialStroke();
return true;
}
}
return false;
Expand Down

0 comments on commit 4a1a176

Please sign in to comment.