mirror of
https://github.com/processing/processing4.git
synced 2026-02-03 21:59:20 +01:00
153 lines
4.3 KiB
Java
153 lines
4.3 KiB
Java
import processing.core.*;
|
|
|
|
|
|
public class agg_bezier_arc {
|
|
|
|
private int m_vertex; // un
|
|
private m_num_vertices; // un
|
|
private float m_vertices[] = new float[26];
|
|
private int m_cmd; // un
|
|
|
|
/**
|
|
* This epsilon is used to prevent us from adding degenerate curves
|
|
* (converging to a single point).
|
|
* The value isn't very critical. Function arc_to_bezier() has a limit
|
|
* of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve
|
|
* becomes inaccurate. But slight exceeding is quite appropriate.
|
|
*/
|
|
static final float bezier_arc_angle_epsilon = 0.01f;
|
|
|
|
|
|
public agg_bezier_arc() {
|
|
m_vertex = 26;
|
|
m_num_vertices = 0;
|
|
m_cmd = path_cmd_line_to;
|
|
}
|
|
|
|
|
|
public agg_bezier_arc(float x, float y,
|
|
float rx, float ry,
|
|
float start_angle,
|
|
float sweep_angle) {
|
|
init(x, y, rx, ry, start_angle, sweep_angle);
|
|
}
|
|
|
|
|
|
public void init(float x, float y,
|
|
float rx, float ry,
|
|
float start_angle,
|
|
float sweep_angle) {
|
|
start_angle = start_angle % PConstants.TWO_PI;
|
|
if (sweep_angle >= 2.0 * pi) sweep_angle = PConstants.TWO_PI;
|
|
if (sweep_angle <= -2.0 * pi) sweep_angle = -PConstants.TWO_PI;
|
|
|
|
if (Math.abs(sweep_angle) < 1e-10) {
|
|
m_num_vertices = 4;
|
|
m_cmd = path_cmd_line_to;
|
|
m_vertices[0] = x + rx * (float)Math.cos(start_angle);
|
|
m_vertices[1] = y + ry * (float)Math.sin(start_angle);
|
|
m_vertices[2] = x + rx * (float)Math.cos(start_angle + sweep_angle);
|
|
m_vertices[3] = y + ry * (float)Math.sin(start_angle + sweep_angle);
|
|
return;
|
|
}
|
|
|
|
float total_sweep = 0.0f;
|
|
float local_sweep = 0.0f;
|
|
float prev_sweep;
|
|
m_num_vertices = 2;
|
|
m_cmd = path_cmd_curve4;
|
|
bool done = false;
|
|
do {
|
|
if (sweep_angle < 0.0f) {
|
|
prev_sweep = total_sweep;
|
|
local_sweep = -pi * 0.5f;
|
|
total_sweep -= pi * 0.5f;
|
|
if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) {
|
|
local_sweep = sweep_angle - prev_sweep;
|
|
done = true;
|
|
}
|
|
} else {
|
|
prev_sweep = total_sweep;
|
|
local_sweep = pi * 0.5f;
|
|
total_sweep += pi * 0.5f;
|
|
if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) {
|
|
local_sweep = sweep_angle - prev_sweep;
|
|
done = true;
|
|
}
|
|
}
|
|
|
|
arc_to_bezier(x, y, rx, ry,
|
|
start_angle,
|
|
local_sweep,
|
|
m_vertices + m_num_vertices - 2);
|
|
|
|
m_num_vertices += 6;
|
|
start_angle += local_sweep;
|
|
}
|
|
while (!done && m_num_vertices < 26);
|
|
}
|
|
|
|
|
|
public void rewind() {
|
|
m_vertex = 0;
|
|
}
|
|
|
|
|
|
public int vertex(float x[], float y[], int offset) { // un
|
|
if (m_vertex >= m_num_vertices) return path_cmd_stop;
|
|
x[offset] = m_vertices[m_vertex];
|
|
y[offset] = m_vertices[m_vertex + 1];
|
|
m_vertex += 2;
|
|
return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
|
|
}
|
|
|
|
|
|
/**
|
|
* Supplemantary functions. num_vertices() actually returns doubled
|
|
* number of vertices. That is, for 1 vertex it returns 2.
|
|
*/
|
|
public int num_vertices() {
|
|
return m_num_vertices;
|
|
}
|
|
|
|
|
|
public void float[] vertices() {
|
|
return m_vertices;
|
|
}
|
|
|
|
|
|
public float[] vertices() {
|
|
return m_vertices;
|
|
}
|
|
|
|
|
|
static public void arc_to_bezier(float cx, float cy, float rx, float ry,
|
|
float start_angle, float sweep_angle,
|
|
float* curve) {
|
|
float x0 = (float) Math.cos(sweep_angle / 2.0f);
|
|
float y0 = (float) Math.sin(sweep_angle / 2.0f);
|
|
float tx = (1.0f - x0) * 4.0f / 3.0f;
|
|
float ty = y0 - tx * x0 / y0;
|
|
float px[] = new float[4];
|
|
float py[] = new float[4];
|
|
px[0] = x0;
|
|
py[0] = -y0;
|
|
px[1] = x0 + tx;
|
|
py[1] = -ty;
|
|
px[2] = x0 + tx;
|
|
py[2] = ty;
|
|
px[3] = x0;
|
|
py[3] = y0;
|
|
|
|
float sn = (float) Math.sin(start_angle + sweep_angle / 2.0f);
|
|
float cs = (float) Math.cos(start_angle + sweep_angle / 2.0f);
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn);
|
|
curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs);
|
|
}
|
|
}
|
|
}
|
|
|
|
|