【问题标题】:drawing oblique rectangle in android在android中绘制斜矩形
【发布时间】:2010-12-28 23:41:04
【问题描述】:

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

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

【问题讨论】:

    标签: android matrix rotation drawable


    【解决方案1】:

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

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

    【讨论】:

    • 我已经有一段时间没有看这段代码了,但它可以使用一些改进。它可以工作,但有些情况可以消除以节省一些代码空间。
    • 如果有任何答案对您有帮助,请通过检查答案左侧的箭头来接受它。
    【解决方案2】:

    解决方法: 而不是绘制矩形画一条线,而是为绘画设置笔触宽度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多