diff --git a/apps/calculation/additional_outputs/complex_graph_cell.cpp b/apps/calculation/additional_outputs/complex_graph_cell.cpp index f00b0ed12..8538b2fe6 100644 --- a/apps/calculation/additional_outputs/complex_graph_cell.cpp +++ b/apps/calculation/additional_outputs/complex_graph_cell.cpp @@ -13,14 +13,16 @@ ComplexGraphView::ComplexGraphView(ComplexModel * complexModel) : void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); + + // Draw grid, axes and graduations drawGrid(ctx, rect); drawAxes(ctx, rect); - // Draw graduations drawLabelsAndGraduations(ctx, rect, Axis::Vertical, true); drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, true); float real = m_complex->real(); float imag = m_complex->imag(); + /* Draw the segment from the origin to the dot (real, imag) of equation * x(t) = t*real and y(t) = t*imag with t in [0,1] */ drawCurve(ctx, rect, 0.0f, 1.0f, 0.01f, @@ -28,6 +30,7 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const { ComplexModel * complexModel = (ComplexModel *)model; return Poincare::Coordinate2D(complexModel->real()*t, complexModel->imag()*t); }, m_complex, nullptr, false, Palette::GreyDark, false); + /* Draw the partial ellipse indicating the angle θ * - the ellipse parameters are a = |real|/5 and b = |imag|/5, * - the parametric ellipse equation is x(t) = a*cos(th*t) and y(t) = b*sin(th*t) @@ -42,29 +45,34 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const { assert(imag != 0.0f); // ComplexGraphView is not displayed for pure real float th = std::atan(std::fabs(real/imag)*std::tan(std::arg(*m_complex))); if (real < 0.0f) { - th += imag < 0.0f ? -M_PI : M_PI; + th += imag < 0.0f ? -M_PI : M_PI; // atan returns value in [-π/2,π/2] } - // Avoid flat ellipsis for edge cases (real = 0) + // Compute ellipsis parameters a and b + float factor = 5.0f; + float a = std::fabs(real)/factor; + float b = std::fabs(imag)/factor; + // Avoid flat ellipsis for edge cases (for real = 0, the case imag = 0 is excluded) if (real == 0.0f) { + a = 1.0f/factor; th = imag < 0.0f ? -M_PI/2.0f : M_PI/2.0f; } + std::complex parameters(a,b); drawCurve(ctx, rect, 0.0f, 1.0f, 0.01f, [](float t, void * model, void * context) { - ComplexModel * complexModel = (ComplexModel *)model; + std::complex parameters = *(std::complex *)model; float th = *(float *)context; - float factor = 5.0f; - float a = std::fabs(complexModel->real())/factor; - float b = std::fabs(complexModel->imag())/factor; - // Avoid flat ellipsis in edge cases (i or -i) - assert(b != 0.0f); - a = a == 0.0f ? 1.0f/factor : a; + float a = parameters.real(); + float b = parameters.imag(); return Poincare::Coordinate2D(a*std::cos(t*th), b*std::sin(t*th)); - }, m_complex, &th, false, Palette::GreyDark, false); + }, ¶meters, &th, false, Palette::GreyDark, false); + // Draw dashed segment to indicate real and imaginary drawSegment(ctx, rect, Axis::Vertical, real, 0.0f, imag, Palette::Red, 1, 3); drawSegment(ctx, rect, Axis::Horizontal, imag, 0.0f, real, Palette::Red, 1, 3); + // Draw complex position on the plan drawDot(ctx, rect, real, imag, Palette::Red, true); + // Draw labels // 're(z)' label drawLabel(ctx, rect, real, 0.0f, "re(z)", Palette::Red, CurveView::RelativePosition::None, imag >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After); @@ -80,16 +88,12 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const { // 'arg(z)' label, the absolute and relative horizontal/vertical positions of this label depends on the quadrant CurveView::RelativePosition horizontalPosition = real >= 0.0f ? CurveView::RelativePosition::After : CurveView::RelativePosition::None; verticalPosition = imag >= 0.0f ? CurveView::RelativePosition::After : CurveView::RelativePosition::Before; - /* factor is the ratio of the angle where we position the label + /* anglePositionRatio is the ratio of the angle where we position the label * For the right half plan, we position the label close to the abscissa axis * and for the left half plan, we position the label at the half angle. The * relative position is chosen accordingly. */ - float factor = real >= 0.0f ? 0.0f : 0.5f; - // The angle represented by flat ellipsis have been avoided previously, so - // we positioned its label consistently - assert(imag != 0.0f); - real = real == 0.0f ? 1.0f : real; - drawLabel(ctx, rect, std::fabs(real)/5.0f*std::cos(factor*th), std::fabs(imag)/5.0f*std::sin(factor*th), "arg(z)", Palette::Red, horizontalPosition, verticalPosition); + float anglePositionRatio = real >= 0.0f ? 0.0f : 0.5f; + drawLabel(ctx, rect, a*std::cos(anglePositionRatio*th), b*std::sin(anglePositionRatio*th), "arg(z)", Palette::Red, horizontalPosition, verticalPosition); } }