我想在android中绘制一个矩形,但不只是指定左,上,右和底。我有4个顶点坐标。矩形不是水平的而是倾斜的,所以类似于下面矩形的图像:
我一直试图看看我是否可以使用矩阵来执行某种旋转或使用canvas.rotate()
,但我仍然不清楚如何做到这一点。有人可以帮我画一个这样的矩形吗?
答案 0 :(得分:2)
我有兴趣看到其他人解决这个问题的方法,但是如果没有更简单的方法,那就是我如何以艰难的方式实现它:
public void drawLineThick(GL10 gl, int thickness, FloatBuffer whichBuffer)
{
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
final float x0 = whichBuffer.get(0);
final float x1 = whichBuffer.get(2);
final float y0 = whichBuffer.get(1);
final float y1 = whichBuffer.get(3);
boolean slopeZeroCase = false;
boolean undefinedSlopeCase = false;
boolean slopeOneCase = false;
boolean slopeNegOneCase = false;
boolean slopeSmall = false;
boolean slopeBig = false;
float boxThickness = thickness * .001f;
//Slope (y2-y1)/(x2-x1)
float m = 0.0f;
//b parameter of y=mx+b formula, b=y-mx
float b = 0.0f;
//Special cases for handling when the slope is zero, undefined
//both (line of length zero), one, or negative one.
if (y1 - y0 == 0)
{
slopeZeroCase = true;
}
if (x1 - x0 == 0)
{
undefinedSlopeCase = true;
}
//If the slope isn't going to be zero or undefined, it's safe to
//actually try to calculate it so that we don't have a "divide by zero"
//by accident
if (slopeZeroCase == false && undefinedSlopeCase == false)
{
m = ((y1 - y0)/(x1 - x0));
b = (y0 - (m*x0));
}
if ( m == 1.0f)
{
slopeOneCase = true;
}
if (m == -1.0f)
{
slopeNegOneCase = true;
}
if ((m > 0 && m < 1) || (m < 0 && m > -1))
{
slopeSmall = true;
}
else
{
slopeBig = true;
}
//float tempFloat[] = new float[8];
//Normal line where there is a slope involved
if (slopeZeroCase == false && undefinedSlopeCase == false && slopeOneCase == false && slopeNegOneCase == false && slopeSmall == true)
{
/**
* Given a sloped line, in order to make it, "thicker",
* one must offset the original line by + and - the
* thickness, in essence creating a box. The formula
* for the points of a given box below (in the direction drawn)
* will be:
*
* p0 p1
* *----------*
* | |
* | |
* | |
* | |
* *----------*
* p3 p2
*
*/
//p1, x
tempFloat[0] = x0;
//p1, y
tempFloat[1] = y0 + boxThickness;
//p2, x
tempFloat[2] = x1;
//p2, y
tempFloat[3] = y1 + boxThickness;
//p3, x
tempFloat[4] = x1;
//p3, y
tempFloat[5] = y1 - boxThickness;
//p4, x
tempFloat[6] = x0;
//p4, y
tempFloat[7] = y0 - boxThickness;
}
else if (slopeZeroCase == false && undefinedSlopeCase == false && slopeOneCase == false && slopeNegOneCase == false && slopeSmall == false)
{
/**
* Given a sloped line, in order to make it, "thicker",
* one must offset the original line by + and - the
* thickness, in essence creating a box. The formula
* for the points of a given box below (in the direction drawn)
* will be:
*
*
*
* p0 p1
* *----------*
* | |
* | |
* | |
* | |
* *----------*
* p3 p2
*
*/
//p1, x
tempFloat[0] = x0 + boxThickness;
//p1, y
tempFloat[1] = y0;
//p2, x
tempFloat[2] = x1 + boxThickness;
//p2, y
tempFloat[3] = y1;
//p3, x
tempFloat[4] = x1 - boxThickness;
//p3, y
tempFloat[5] = y1;
//p4, x
tempFloat[6] = x0 - boxThickness;
//p4, y
tempFloat[7] = y0;
}
//Horizontal line case, only need to change the y to be +- thickness
else if (slopeZeroCase == true && undefinedSlopeCase == false && slopeOneCase == false && slopeNegOneCase == false)
{
//Log.i("draw", "Horizontal");
//p1, x
tempFloat[0] = x0;
//p1, y
tempFloat[1] = y0 + boxThickness;
//p2, x
tempFloat[2] = x1;
//p2, y
tempFloat[3] = y1 + boxThickness;
//p3, x
tempFloat[4] = x1;
//p3, y
tempFloat[5] = y1 - boxThickness;
//p4, x
tempFloat[6] = x0;
//p4, y
tempFloat[7] = y0 - boxThickness;
}
//Vertical line case, only need to change the x to be +- thickness
else if (slopeZeroCase == false && undefinedSlopeCase == true && slopeOneCase == false && slopeNegOneCase == false)
{
//Log.i("draw", "Vertical");
//p1, x
tempFloat[0] = x0 + boxThickness;
//p1, y
tempFloat[1] = y0;
//p2, x
tempFloat[2] = x1 + boxThickness;
//p2, y
tempFloat[3] = y1;
//p3, x
tempFloat[4] = x1 - boxThickness;
//p3, y
tempFloat[5] = y1;
//p4, x
tempFloat[6] = x0 - boxThickness;
//p4, y
tempFloat[7] = y0;
}
//Case where slope = 1
else if (slopeZeroCase == false && undefinedSlopeCase == false && slopeOneCase == true && slopeNegOneCase == false)
{
//Log.i("draw", "OneSlope");
//p1, x
tempFloat[0] = y0 - boxThickness;
//p1, y
tempFloat[1] = x0 + boxThickness;
//p2, x
tempFloat[2] = y1 - boxThickness;
//p2, y
tempFloat[3] = x1 + boxThickness;
//p3, x
tempFloat[4] = y1 + boxThickness;
//p3, y
tempFloat[5] = x1 - boxThickness;
//p4, x
tempFloat[6] = y0 + boxThickness;
//p4, y
tempFloat[7] = x0 - boxThickness;
}
//Case where slope = -1
else if (slopeZeroCase == false && undefinedSlopeCase == false && slopeOneCase == false && slopeNegOneCase == true)
{
Log.i("draw", "OneSlope");
//p1, x
tempFloat[0] = -y0 + boxThickness;
//p1, y
tempFloat[1] = -x0 + boxThickness;
//p2, x
tempFloat[2] = -y1 + boxThickness;
//p2, y
tempFloat[3] = -x1 + boxThickness;
//p3, x
tempFloat[4] = -y1 - boxThickness;
//p3, y
tempFloat[5] = -x1 - boxThickness;
//p4, x
tempFloat[6] = -y0 - boxThickness;
//p4, y
tempFloat[7] = -x0 - boxThickness;
}
//Allocate the wrapped buffers that OpenGL ES uses for drawing, buffers changed to
//be allocated at class scope so that they're not re-allocated every time this
//algorithm is run
//ByteBuffer tempBoxByteBuffer = ByteBuffer.allocateDirect(tempFloat.length * 4);
//tempBoxByteBuffer.order(ByteOrder.nativeOrder());
//FloatBuffer boxFloatBuffer = tempBoxByteBuffer.asFloatBuffer();
boxFloatBuffer.put(tempFloat);
boxFloatBuffer.position(0);
//Draw triangles using points p0, p1, and p2 for the first, and
//p0, p3, and p2 for the second, filling in between. See box
//above for diagram of points. Indices also changed to be allocated at class scope
//short indices[] = {0, 1, 2, 0, 3, 2};
//ByteBuffer tempIndiceBuffer = ByteBuffer.allocateDirect(indices.length * 2);
//tempIndiceBuffer.order(ByteOrder.nativeOrder());
//ShortBuffer indiceBuffer = tempIndiceBuffer.asShortBuffer();
//indiceBuffer.put(indices);
//indiceBuffer.position(0);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, boxFloatBuffer);
//gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 2);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indiceBuffer);
}
这个特定的实现已经完成,所以我可以有一个填充框,这不是默认的OpenGL ES功能。相反,我所做的是绘制两个三角形。数学包括几个特殊情况,零斜率,一个斜率,一个未定义的斜率,斜率大于0但小于一个或小于零但大于负一个情况,或斜率大于一个或小于消极的一个案例。你所要做的就是在每组点之间绘制一个线环而不是一个三角形,你将拥有一个未填充的框。
答案 1 :(得分:0)
变通方法: 而不是绘制矩形绘制一条线,但设置绘画的笔触宽度。