在android中绘制斜矩形

发布于 2024-10-09 12:08:09 字数 252 浏览 2 评论 0原文

我想在android中绘制一个矩形,但不仅仅是通过指定左、上、右和下。我所拥有的是 4 个顶点坐标。该矩形不是水平的而是倾斜的,因此类似于下面的矩形图像:

image of an obliquequartz

我已经一直在尝试查看是否可以使用矩阵来执行某种旋转或使用canvas.rotate(),但我仍然不清楚如何做到这一点。有人可以帮我画这样一个矩形吗?

I wanted to draw a rectangle in android, but not just by specifying the left, top, right and bottom. What I have are 4 vertex coordinates. The rectangle is not horizontal but oblique, so something like the image of the rectangle below:

image of an oblique rectangle

I've been trying to see if I can use a matrix to perform some kind of rotation or use canvas.rotate(), but I'm still not clear how to do it. Can somebody help me with how to draw such a rectangle?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空城缀染半城烟沙 2024-10-16 12:08:10

我很想看看其他人对这个问题的解决方案,但如果没有更简单的方法,这就是我如何以困难的方式实现它:

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 或小于零但大于负的一种情况,或者斜率大于 1 或小于阴性一例。您所要做的就是在每组点之间绘制一条线环而不是三角形,然后您将得到一个未填充的框。

I'd be interested in seeing somebody else's solution to this problem, but if there isn't an easier way, here's how I implemented it the hard way:

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);

}

This particular implementation was done so that I could have a filled-in box, which is not a default OpenGL ES capability. What I did, instead, was draw two triangles. The math includes several special cases, a zero slope, a one slope, an undefined slope, a slope is greater than 0 but less than one or less than zero but greater than negative one case, or a slope is greater than one or less than negative one case. All you have to do is draw a line loop instead of a triangle between each set of points, and you'll have a non-filled box.

清眉祭 2024-10-16 12:08:10

解决方法:
不是绘制矩形而是绘制一条线,而是设置绘画的描边宽度。

workaround :
instead of drawing rectangle draw a line but set stroke width for paint.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文