From 9e822e85e546e8ab460b65bc512a624a2d29c241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Mar 2020 16:38:29 +0100 Subject: [PATCH] [apps/shared] CurveView: implement drawArrow --- apps/shared/curve_view.cpp | 41 ++++++++++++++++++++++++++++++++++++++ apps/shared/curve_view.h | 25 +++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index e7337faf7..fd7f25090 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -452,6 +452,47 @@ void CurveView::drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor ctx->blendRectWithMask(dotRect, color, mask, workingBuffer); } + +void CurveView::drawArrow(KDContext * ctx, KDRect rect, float x, float y, float dx, float dy, KDColor color, KDCoordinate pixelArrowLength, float angle) const { + /* Let's call the following variables L and l: + * + * / | + * / | + * / l + * / | + * / | + * <-------------------------------------------------- + * \ + * \ + * \ + * \ + * \ + * + * ----- L ----- + * + **/ + assert(angle >= 0.0f); + /* We compute the arrow segments in pixels in order to correctly size the + * arrow without depending on the displayed range. + * Warning: the computed values are relative so we need to add/subtract the + * pixel position of 0s. */ + float x0Pixel = floatToPixel(Axis::Horizontal, 0.0f); + float y0Pixel = floatToPixel(Axis::Vertical, 0.0f); + float dxPixel = floatToPixel(Axis::Horizontal, dx) - x0Pixel; + float dyPixel = y0Pixel - floatToPixel(Axis::Vertical, dy); + float dx2dy2 = std::sqrt(dxPixel*dxPixel+dyPixel*dyPixel); + float L = pixelArrowLength; + float l = angle*L; + + float arrow1dx = pixelToFloat(Axis::Horizontal, x0Pixel + L*dxPixel/dx2dy2 + l*dyPixel/dx2dy2); + float arrow1dy = pixelToFloat(Axis::Vertical, y0Pixel - (L*dyPixel/dx2dy2 - l*dxPixel/dx2dy2)); + drawSegment(ctx, rect, x, y, x - arrow1dx, y - arrow1dy, color, false); + + float arrow2dx = pixelToFloat(Axis::Horizontal, x0Pixel + L*dxPixel/dx2dy2 - l*dyPixel/dx2dy2); + float arrow2dy = pixelToFloat(Axis::Vertical, y0Pixel - (L*dyPixel/dx2dy2 + l*dxPixel/dx2dy2)); + drawSegment(ctx, rect, x, y, x - arrow2dx, y - arrow2dy, color, false); +} + void CurveView::drawGrid(KDContext * ctx, KDRect rect) const { KDColor boldColor = Palette::GreyMiddle; KDColor lightColor = Palette::GreyWhite; diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index ee5aafbd6..9470aad49 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -75,6 +75,31 @@ protected: Large }; void drawDot(KDContext * ctx, KDRect rect, float x, float y, KDColor color, Size size = Size::Small) const; + /* 'drawArrow' draws the edge of an arrow pointing to (x,y) with the + * orientation (dx,dy). + * The parameters defining the shape of the arrow are the length in pixel of + * the projection of the arrow on the segment -'pixelArrowLength'- and the + * tangent of the angle between the segment and each wing of the arrow called + * 'angle'. + * + * / | + * / | + * / L + * / | + * / | + * <-------------------------------------------------- + * \ + * \ + * \ + * \ + * \ + * + * <--- pl ---> + * + * pl = pixelArrowLength + * tan(angle) = L/pl + */ + void drawArrow(KDContext * ctx, KDRect rect, float x, float y, float dx, float dy, KDColor color, KDCoordinate pixelArrowLength = 10, float angle = 0.4f) const; void drawGrid(KDContext * ctx, KDRect rect) const; void drawAxes(KDContext * ctx, KDRect rect) const; void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const;