blob: bf6448163ab150891737119c9eca9e4c5ce3eaee [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
//
#include "spinel/ext/geometry/ellipse.h"
#include "spinel/spinel_assert.h"
//
// Not a constant found in <math.h>
//
#ifndef SPN_M_SQRT3_2
#define SPN_M_SQRT3_2 0.86602540378443864676 // sqrt(3)/2
#endif
//
//
//
// clang-format off
#define SPN_SWEEP_COS_2 0.5f // cosf(120° / 2.0)
#define SPN_SWEEP_SIN_2 (float)SPN_M_SQRT3_2 // sinf(120° / 2.0)
#define SPN_SWEEP_K 0.5f // 2.0 * 0.5 * 0.5
#define SPN_SWEEP_K_INV 2.0f // 1 / 0.5
// clang-format on
//
//
//
#define SPN_ELLIPSE_SWEEP(x1_, y1_, x2_, y2_) \
if ((err = spinel_path_builder_rat_quad_to(path_builder, /* */ \
x1_, \
y1_, \
x2_, \
y2_, \
SPN_SWEEP_COS_2)) != SPN_SUCCESS) \
return err;
//
// Draw an ellipse with 3 rational quads
//
spinel_result_t
spinel_path_builder_ellipse(spinel_path_builder_t path_builder, //
float cx,
float cy,
float rx,
float ry)
{
//
// calculate 3 end points
//
float const px0 = cx + rx;
float const py0 = cy;
float const pxE = cx - rx * SPN_SWEEP_COS_2;
float const py1 = cy + ry * SPN_SWEEP_SIN_2;
// px2 = px1
float const py2 = cy - ry * SPN_SWEEP_SIN_2;
//
// calculate 3 control points using A. Cantóna method
//
float const qx0 = (cx * (SPN_SWEEP_K - 2.0f) + px0 + pxE) * SPN_SWEEP_K_INV;
float const qy0 = (cy * (SPN_SWEEP_K - 2.0f) + py0 + py1) * SPN_SWEEP_K_INV;
float const qx1 = (cx * (SPN_SWEEP_K - 2.0f) + pxE + pxE) * SPN_SWEEP_K_INV;
float const qy1 = (cy * (SPN_SWEEP_K - 2.0f) + py1 + py2) * SPN_SWEEP_K_INV;
float const qx2 = (cx * (SPN_SWEEP_K - 2.0f) + pxE + px0) * SPN_SWEEP_K_INV;
float const qy2 = (cy * (SPN_SWEEP_K - 2.0f) + py2 + py0) * SPN_SWEEP_K_INV;
//
// emit 3 arc control cages
//
spinel_path_builder_move_to(path_builder, px0, py0);
spinel_result_t err;
SPN_ELLIPSE_SWEEP(qx0, qy0, pxE, py1);
SPN_ELLIPSE_SWEEP(qx1, qy1, pxE, py2);
SPN_ELLIPSE_SWEEP(qx2, qy2, px0, py0);
return SPN_SUCCESS;
}
//
//
//