Skip to content

Commit

Permalink
Traktor: Smooth edges in graph control.
Browse files Browse the repository at this point in the history
  • Loading branch information
apistol78 committed Jun 10, 2024
1 parent 460a87b commit 91729a6
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 12 deletions.
9 changes: 9 additions & 0 deletions code/Core/Math/Bezier3rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,13 @@ void Bezier3rd::approximate(float errorThreshold, int maxSubdivisions, AlignedVe
approximateSubdivide(*this, errorThreshold, maxSubdivisions, outQuadratic);
}

Bezier3rd Bezier3rd::fromCatmullRom(const Vector2& cp0, const Vector2& cp1, const Vector2& cp2, const Vector2& cp3, float tension)
{
const Vector2 bcp0 = cp1;
const Vector2 bcp1 = cp1 + (cp2 - cp0) / (6.0f * tension);
const Vector2 bcp2 = cp2 - (cp3 - cp1) / (6.0f * tension);
const Vector2 bcp3 = cp2;
return Bezier3rd(bcp0, bcp1, bcp2, bcp3);
}

}
4 changes: 3 additions & 1 deletion code/Core/Math/Bezier3rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class T_DLLCLASS Bezier3rd

float flatness() const;

/*! Check if curve is sufficently flat.
/*! Check if curve is sufficiently flat.
*
* \param tolerance Tolerance value as defined by PostScript.
*/
Expand All @@ -54,6 +54,8 @@ class T_DLLCLASS Bezier3rd
void split(float t, Bezier3rd& outLeft, Bezier3rd& outRight) const;

void approximate(float errorThreshold, int maxSubdivisions, AlignedVector< Bezier2nd >& outQuadratic) const;

static Bezier3rd fromCatmullRom(const Vector2& cp0, const Vector2& cp1, const Vector2& cp2, const Vector2& cp3, float tension);
};

}
Expand Down
25 changes: 19 additions & 6 deletions code/Ui/Graph/Edge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,24 +229,37 @@ void Edge::paint(GraphControl* graph, GraphCanvas* canvas, const Size& offset, I
const Point s = graph->pixel(m_source->getPosition()) + offset;
const Point d = graph->pixel(m_destination->getPosition()) + offset;

calculateLinearSpline(graph, s, d, m_spline);
// calculateLinearSpline(graph, s, d, m_spline);
// canvas->drawLines(m_spline, graph->pixel(hot ? 4_ut : m_thickness));

int32_t dx = (d.x - s.x) / 4;
int32_t dy = (d.y - s.y) / 8;

dx = std::max(dx, 30);

m_spline.resize(0);
m_spline.push_back(Point(s.x - 10, s.y));
m_spline.push_back(s);
m_spline.push_back(Point(s.x + dx, s.y + dy));
m_spline.push_back(Point(d.x - dx, d.y - dy));
m_spline.push_back(d);
m_spline.push_back(Point(d.x + 10, d.y));
canvas->drawSpline(m_spline, graph->pixel(m_thickness));

#if defined(_DEBUG)
canvas->setBackground(Color4ub(255, 255, 255, 255));
canvas->setBackground(Color4ub(255, 255, 255, 180));
for (const auto& p : m_spline)
{
canvas->fillRect(
Rect(
Point(p.x - 1, p.y - 1),
Size(2, 2)
Point(p.x - 4, p.y - 4),
Size(8, 8)
)
);
}
canvas->setBackground(color);
#endif

canvas->drawLines(m_spline, graph->pixel(hot ? 4_ut : m_thickness));

const Point at = graph->pixel(m_destination->getPosition()) + offset;
const Point arrow[] =
{
Expand Down
13 changes: 13 additions & 0 deletions code/Ui/Graph/GraphCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ void GraphCanvas::drawCurve(const Point& start, const Point& control, const Poin
m_canvas->setPenThickness(1);
}

void GraphCanvas::drawSpline(const AlignedVector< Point >& pnts, int32_t thickness)
{
std::vector< Point > tpnts;
tpnts.reserve(pnts.size());

for (const auto& pnt : pnts)
tpnts.push_back(pnt * m_scale);

m_canvas->setPenThickness((int32_t)std::ceil(thickness * m_scale));
m_canvas->drawSpline(tpnts);
m_canvas->setPenThickness(1);
}

void GraphCanvas::drawRect(const Rect& rc)
{
m_canvas->drawRect(rc * m_scale);
Expand Down
2 changes: 2 additions & 0 deletions code/Ui/Graph/GraphCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class GraphCanvas : public Object

void drawCurve(const Point& start, const Point& control, const Point& end, int32_t thickness);

void drawSpline(const AlignedVector< Point >& pnts, int32_t thickness);

void drawRect(const Rect& rc);

void fillRect(const Rect& rc);
Expand Down
56 changes: 51 additions & 5 deletions code/Ui/Win32/CanvasDirect2DWin32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <limits>
#include "Core/Log/Log.h"
#include "Core/Math/Bezier3rd.h"
#include "Core/Misc/String.h"
#include "Core/Thread/Atomic.h"
#include "Ui/Application.h"
Expand All @@ -29,6 +30,11 @@ ComRef< ID2D1Factory > s_d2dFactory;
ComRef< IDWriteFactory > s_dwFactory;
int32_t s_instanceCount = 0;

Vector2 pnt2vec(const Point& pt)
{
return Vector2(pt.x, pt.y);
}

}

CanvasDirect2DWin32::CanvasDirect2DWin32()
Expand Down Expand Up @@ -506,6 +512,50 @@ void CanvasDirect2DWin32::drawEllipticArc(int x, int y, int w, int h, float star

void CanvasDirect2DWin32::drawSpline(const Point* pnts, int npnts)
{
HRESULT hr;

if (npnts < 4)
return;

ComRef< ID2D1PathGeometry > d2dPathGeometry;
s_d2dFactory->CreatePathGeometry(&d2dPathGeometry.getAssign());

ComRef< ID2D1GeometrySink > d2dGeometrySink;
hr = d2dPathGeometry->Open(&d2dGeometrySink.getAssign());
if (FAILED(hr))
return;

for (int32_t i = 0; i <= npnts - 4; ++i)
{
const Bezier3rd b = Bezier3rd::fromCatmullRom(
pnt2vec(pnts[i + 0]),
pnt2vec(pnts[i + 1]),
pnt2vec(pnts[i + 2]),
pnt2vec(pnts[i + 3]),
1.0f
);

if (i == 0)
{
d2dGeometrySink->BeginFigure(
D2D1::Point2F(b.cp0.x, b.cp0.y),
D2D1_FIGURE_BEGIN_HOLLOW
);
}

D2D1_BEZIER_SEGMENT bs;
bs.point1 = D2D1::Point2F(b.cp1.x, b.cp1.y);
bs.point2 = D2D1::Point2F(b.cp2.x, b.cp2.y);
bs.point3 = D2D1::Point2F(b.cp3.x, b.cp3.y);
d2dGeometrySink->AddBezier(&bs);
}

d2dGeometrySink->EndFigure(D2D1_FIGURE_END_OPEN);
d2dGeometrySink->Close();

m_d2dRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
m_d2dRenderTarget->DrawGeometry(d2dPathGeometry, m_d2dForegroundBrush, m_strokeWidth);
m_d2dRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
}

void CanvasDirect2DWin32::fillRect(const Rect& rc)
Expand Down Expand Up @@ -630,11 +680,7 @@ void CanvasDirect2DWin32::drawPolygon(const Point* pnts, int npnts)
d2dGeometrySink->Close();

m_d2dRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
m_d2dRenderTarget->DrawGeometry(
d2dPathGeometry,
m_d2dForegroundBrush,
m_strokeWidth
);
m_d2dRenderTarget->DrawGeometry(d2dPathGeometry, m_d2dForegroundBrush, m_strokeWidth);
m_d2dRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
}

Expand Down

0 comments on commit 91729a6

Please sign in to comment.