Skip to content

Commit

Permalink
Merge pull request #3498 from DavidBauer1984/develop-slur-helper
Browse files Browse the repository at this point in the history
Move slur adjustment to functor
  • Loading branch information
lpugin authored Aug 21, 2023
2 parents 86869e8 + 0f24349 commit 3ca793b
Show file tree
Hide file tree
Showing 4 changed files with 968 additions and 951 deletions.
119 changes: 118 additions & 1 deletion include/vrv/adjustslursfunctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,36 @@
#define __VRV_ADJUSTSLURSFUNCTOR_H__

#include "functor.h"
#include "slur.h"

namespace vrv {

//----------------------------------------------------------------------------
// ControlPointConstraint
//----------------------------------------------------------------------------
/**
* This represents a constraint ax + by >= c where x and y are
* vertical control point adjustments
*/
struct ControlPointConstraint {
double a;
double b;
double c;
};

//----------------------------------------------------------------------------
// ControlPointAdjustment
//----------------------------------------------------------------------------
/**
* A vertical adjustment of bezier control points
*/
struct ControlPointAdjustment {
int leftShift;
int rightShift;
bool moveUpwards;
int requestedStaffSpace;
};

//----------------------------------------------------------------------------
// AdjustSlursFunctor
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -39,6 +66,11 @@ class AdjustSlursFunctor : public DocFunctor {
*/
bool HasCrossStaffSlurs() const { return m_crossStaffSlurs; }

/*
* Reset the current slur and curve
*/
void ResetCurrent();

/*
* Functor interface
*/
Expand All @@ -50,12 +82,97 @@ class AdjustSlursFunctor : public DocFunctor {
protected:
//
private:
//
/**
* High level helper functions
*/
///@{
void AdjustSlur(int unit) const;

void AdjustOuterSlur(const ArrayOfFloatingCurvePositioners &innerCurves, int unit) const;
///@}

/**
* Intermediate level helper functions
*/
///@{
// Discard certain spanned elements
void FilterSpannedElements(const BezierCurve &bezierCurve, int margin) const;

// Detect collisions near the endpoints
NearEndCollision DetectCollisionsNearEnd(const BezierCurve &bezierCurve, int margin) const;

// Calculate the vertical shift of the slur end points
std::pair<int, int> CalcEndPointShift(const BezierCurve &bezierCurve, double flexibility, int margin) const;

// Apply the vertical shift of the slur end points
void ApplyEndPointShift(BezierCurve &bezierCurve, int endPointShiftLeft, int endPointShiftRight) const;

// Calculate slur from bulge values
void AdjustSlurFromBulge(BezierCurve &bezierCurve, int unit) const;

// Check whether control points should be adjusted horizontally
bool AllowControlOffsetAdjustment(const BezierCurve &bezierCurve, double symmetry, int unit) const;

// Calculate the horizontal control point offset
std::tuple<bool, int, int> CalcControlPointOffset(const BezierCurve &bezierCurve, int margin) const;

// Calculate the vertical control point shift
ControlPointAdjustment CalcControlPointVerticalShift(
const BezierCurve &bezierCurve, double symmetry, int margin) const;

// Solve the constraints for vertical control point adjustment
std::pair<int, int> SolveControlPointConstraints(
const std::list<ControlPointConstraint> &constraints, double symmetry = 0.0) const;

// Improve the slur shape by adjusting the control point heights
void AdjustSlurShape(BezierCurve &bezierCurve, curvature_CURVEDIR dir, int unit) const;
///@}

/**
* Intermediate level helper functions for adjustment w.r.t. inner slurs
*/
///@{
// Calculate the vertical control point shift
ControlPointAdjustment CalcControlPointShift(const BezierCurve &bezierCurve,
const ArrayOfFloatingCurvePositioners &innerCurves, double symmetry, int margin) const;

// Calculate the vertical shift of the slur end points
std::pair<int, int> CalcEndPointShift(const BezierCurve &bezierCurve,
const ArrayOfFloatingCurvePositioners &innerCurves, double flexibility, int margin) const;
///@}

/**
* Low level helper functions
*/
///@{
// Shift end points for collisions nearby
void ShiftEndPoints(int &shiftLeft, int &shiftRight, double ratio, int intersection, double flexibility,
bool isBelow, char spanningType) const;

// Calculate the full and partial shift radii
std::pair<double, double> CalcShiftRadii(bool forShiftLeft, double flexibility, char spanningType) const;

// Determine a quadratic interpolation function between zero and one and evaluate it
double CalcQuadraticInterpolation(double zeroAt, double oneAt, double arg) const;

// Rotate the slope by a given number of degrees, but choose smaller angles if already close to the vertical axis
// Choose doublingBound as the positive slope value where doubling has the same effect as rotating:
// tan(atan(doublingBound) + degrees * PI / 180.0) ≈ 2.0 * doublingBound
double RotateSlope(double slope, double degrees, double doublingBound, bool upwards) const;

// Calculate the minimal angle <)C1P1P2 or <)P1P2C2
float GetMinControlPointAngle(const BezierCurve &bezierCurve, float angle, int unit) const;
///@}

public:
//
private:
// Indicates that there is at least one cross-staff slur
bool m_crossStaffSlurs;
// The current slur
Slur *m_currentSlur;
// The curve positioner
FloatingCurvePositioner *m_currentCurve;
};

} // namespace vrv
Expand Down
117 changes: 2 additions & 115 deletions include/vrv/slur.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,6 @@ struct NearEndCollision {
bool endPointsAdjusted;
};

//----------------------------------------------------------------------------
// ControlPointConstraint
//----------------------------------------------------------------------------
/**
* This represents a constraint ax + by >= c where x and y are
* vertical control point adjustments
*/
struct ControlPointConstraint {
double a;
double b;
double c;
};

//----------------------------------------------------------------------------
// ControlPointAdjustment
//----------------------------------------------------------------------------
/**
* A vertical adjustment of bezier control points
*/
struct ControlPointAdjustment {
int leftShift;
int rightShift;
bool moveUpwards;
int requestedStaffSpace;
};

// Helper enum classes
enum class SlurCurveDirection { None, Above, Below, AboveBelow, BelowAbove };
enum class PortatoSlurType { None, StemSide, Centered };
Expand Down Expand Up @@ -195,18 +169,6 @@ class Slur : public ControlElement,
*/
void InitBezierControlSides(BezierCurve &bezier, curvature_CURVEDIR curveDir) const;

/**
* Slur adjustment
*/
///@{
void AdjustSlur(const Doc *doc, FloatingCurvePositioner *curve, int unit);

void AdjustOuterSlur(
const Doc *doc, FloatingCurvePositioner *curve, const ArrayOfFloatingCurvePositioners &innerCurves, int unit);

float GetAdjustedSlurAngle(const Doc *doc, Point &p1, Point &p2, curvature_CURVEDIR curveDir) const;
///@}

//----------//
// Functors //
//----------//
Expand Down Expand Up @@ -258,83 +220,8 @@ class Slur : public ControlElement,
bool StartsOnBeam() const { return this->HasBoundaryOnBeam(true); }
bool EndsOnBeam() const { return this->HasBoundaryOnBeam(false); }
bool HasBoundaryOnBeam(bool isStart) const;
///@}

/**
* Adjust slur position based on overlapping objects within its spanning elements
*/
///@{
// Discard certain spanned elements
void FilterSpannedElements(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin);

// Detect collisions near the endpoints
NearEndCollision DetectCollisionsNearEnd(
FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin);

// Calculate the vertical shift of the slur end points
std::pair<int, int> CalcEndPointShift(
FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, double flexibility, int margin);

// Apply the vertical shift of the slur end points
void ApplyEndPointShift(
FloatingCurvePositioner *curve, BezierCurve &bezierCurve, int endPointShiftLeft, int endPointShiftRight);

// Calculate slur from bulge values
void AdjustSlurFromBulge(FloatingCurvePositioner *curve, BezierCurve &bezierCurve, int unit);

// Check whether control points should be adjusted horizontally
bool AllowControlOffsetAdjustment(const BezierCurve &bezierCurve, double symmetry, int unit) const;

// Calculate the horizontal control point offset
std::tuple<bool, int, int> CalcControlPointOffset(
FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin);

// Calculate the vertical control point shift
ControlPointAdjustment CalcControlPointVerticalShift(
FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, double symmetry, int margin);

// Solve the constraints for vertical control point adjustment
std::pair<int, int> SolveControlPointConstraints(
const std::list<ControlPointConstraint> &constraints, double symmetry = 0.0) const;

// Improve the slur shape by adjusting the control point heights
void AdjustSlurShape(BezierCurve &bezierCurve, curvature_CURVEDIR dir, int unit);
///@}

/**
* Adjust slur position based on inner slurs
*/
///@{
// Calculate the vertical control point shift
ControlPointAdjustment CalcControlPointShift(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve,
const ArrayOfFloatingCurvePositioners &innerCurves, double symmetry, int margin);

// Calculate the vertical shift of the slur end points
std::pair<int, int> CalcEndPointShift(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve,
const ArrayOfFloatingCurvePositioners &innerCurves, double flexibility, int margin);
///@}

/**
* Low level helper functions for slur adjustment
*/
///@{
// Shift end points for collisions nearby
void ShiftEndPoints(int &shiftLeft, int &shiftRight, double ratio, int intersection, double flexibility,
bool isBelow, char spanningType) const;

// Calculate the full and partial shift radii
std::pair<double, double> CalcShiftRadii(bool forShiftLeft, double flexibility, char spanningType) const;

// Determine a quadratic interpolation function between zero and one and evaluate it
double CalcQuadraticInterpolation(double zeroAt, double oneAt, double arg) const;

// Rotate the slope by a given number of degrees, but choose smaller angles if already close to the vertical axis
// Choose doublingBound as the positive slope value where doubling has the same effect as rotating:
// tan(atan(doublingBound) + degrees * PI / 180.0) ≈ 2.0 * doublingBound
double RotateSlope(double slope, double degrees, double doublingBound, bool upwards) const;

// Calculate the minimal angle <)C1P1P2 or <)P1P2C2
float GetMinControlPointAngle(const BezierCurve &bezierCurve, float angle, int unit) const;
// Angle adjustment
float GetAdjustedSlurAngle(const Doc *doc, Point &p1, Point &p2, curvature_CURVEDIR curveDir) const;
///@}

public:
Expand Down
Loading

0 comments on commit 3ca793b

Please sign in to comment.