我想在opengl surfaceview上使用中心点,起点,终点绘制弧线。到目前为止,我已尝试过以下代码。如果我们手动给出 start_line_angle 和 end_line_angle 的值,则此函数会绘制预期的弧(例如 start_line_angle = 0且 end_line_angle = 90)度。
但是我需要用给定的坐标绘制圆弧(中心点,起点,终点)并以编程方式计算 start_line_angle 和 end_line_angle 。 该给定函数使用给定参数绘制弧但不给出期望结果。我浪费了我2天的时间。提前谢谢。
private void drawArc(GL10 gl, float radius, float cx, float cy, float start_point_x, float start_point_y, float end_point_x, float end_point_y) {
gl.glLineWidth(1);
int start_line_angle;
double sLine = Math.toDegrees(Math.atan((cy - start_point_y) / (cx - start_point_x))); //normal trigonometry slope = tan^-1(y2-y1)/(x2-x1) for line first
double eLine = Math.toDegrees(Math.atan((cy - end_point_y) / (cx - end_point_x))); //normal trigonometry slope = tan^-1(y2-y1)/(x2-x1) for line second
//cast from double to int after round
int start_line_Slope = (int) (sLine + 0.5);
/**
* mapping the tiriogonometric angle system to glsurfaceview angle system
* since angle system in trigonometric system starts in anti clockwise
* but in opengl glsurfaceview angle system starts in clock wise and the starting angle is 90 degree of general trigonometric angle system
**/
if (start_line_Slope <= 90) {
start_line_angle = 90 - start_line_Slope;
} else {
start_line_angle = 360 - start_line_Slope + 90;
}
// int start_line_angle = 270;
// int end_line_angle = 36;
//casting from double to int
int end_line_angle = (int) (eLine + 0.5);
if (start_line_angle > end_line_angle) {
start_line_angle = start_line_angle - 360;
}
int nCount = 0;
float[] stVertexArray = new float[2 * (end_line_angle - start_line_angle)];
float[] newStVertextArray;
FloatBuffer sampleBuffer;
// stVertexArray[0] = cx;
// stVertexArray[1] = cy;
for (int nR = start_line_angle; nR < end_line_angle; nR++) {
float fX = (float) (cx + radius * Math.sin((float) nR * (1 * (Math.PI / 180))));
float fY = (float) (cy + radius * Math.cos((float) nR * (1 * (Math.PI / 180))));
stVertexArray[nCount * 2] = fX;
stVertexArray[nCount * 2 + 1] = fY;
nCount++;
}
//taking making the stVertextArray's data in reverse order
reverseArray = new float[stVertexArray.length];//-2 so that no repeatation occurs of first value and end value
int count = 0;
for (int i = (stVertexArray.length) / 2; i > 0; i--) {
reverseArray[count] = stVertexArray[(i - 1) * 2 + 0];
count++;
reverseArray[count] = stVertexArray[(i - 1) * 2 + 1];
count++;
}
//reseting the counter to initial value
count = 0;
int finalArraySize = stVertexArray.length + reverseArray.length;
newStVertextArray = new float[finalArraySize];
/**Now adding all the values to the single newStVertextArray to draw an arc**/
//adding stVertextArray to newStVertextArray
for (float d : stVertexArray) {
newStVertextArray[count++] = d;
}
//adding reverseArray to newStVertextArray
for (float d : reverseArray) {
newStVertextArray[count++] = d;
}
Log.d("stArray", stVertexArray.length + "");
Log.d("reverseArray", reverseArray.length + "");
Log.d("newStArray", newStVertextArray.length + "");
ByteBuffer bBuff = ByteBuffer.allocateDirect(newStVertextArray.length * 4);
bBuff.order(ByteOrder.nativeOrder());
sampleBuffer = bBuff.asFloatBuffer();
sampleBuffer.put(newStVertextArray);
sampleBuffer.position(0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, sampleBuffer);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, nCount * 2);
gl.glLineWidth(1);
}
答案 0 :(得分:0)
要从三角学开始,您可能不会简单地使用atan
来查找角度。您需要检查向量所在的象限,并增加或减少从atan
获得的结果。更好的是使用atan2
,其中应包含dx
和dy
并为您完成工作。
您似乎创建了缓冲区,以便按度数创建一个点。对于可能太小的大半径而言,这不是最佳解决方案,对于小半径而言,这太过分了。细分也应该包括半径,使点数N
为N = abs((int)(deltaAngle*radius*tessellationFactor))
,然后使用angleFragment = deltaAngle/N
,但要确保N
大于0(N = N?N:1
) 。然后,缓冲区大小为2*(N+1)
浮点数,迭代次数为for(int i=0; i<=N; i++) angle = startAngle + angleFragment*i;
。
正如已经指出的那样,你需要定义弧的半径。以你的方式使用外部源是很正常的,只需将其强制为该值,但使用3个点作为中心和两个边界。其他一些通常有意义的选择是:
要插入半径,您需要获得两个半径startRadius
和endRadius
。然后你需要找到上面已经用作deltaAngle
的整体半径(在计算这个时要注意,它看起来更复杂,例如从320度到10度绘制会产生{{1} })。无论如何,特定点的半径只是deltaAngle = 50
。这表示极坐标系统中的简单线性插值,通常用于在矩阵中插入向量,是获得精美动画的核心功能。
还有其他一些方法可以获得更好的性能,但我不会建议它们,除非你需要优化你的代码,这应该是非常晚的生产。您可以简单地继续走向下一个点并修正半径(这只是一个概念):
radius = startRadius + (endRadius-startRadius)*abs((angleFragment*i)/deltaAngle)