рисование косого прямоугольника в Android - PullRequest
2 голосов
/ 29 декабря 2010

Я хотел нарисовать прямоугольник в Android, но не просто указав левый, верхний, правый и нижний.У меня есть 4 координаты вершины.Прямоугольник не горизонтальный, а наклонный, поэтому что-то вроде изображения прямоугольника ниже:

image of an oblique rectangle

Я пытался понять, могу ли я использовать матрицу для выполнения какого-либовращения или используйте canvas.rotate(), но мне все еще не ясно, как это сделать.Может кто-нибудь помочь мне с тем, как нарисовать такой прямоугольник?

Ответы [ 2 ]

2 голосов
/ 29 декабря 2010

Мне было бы интересно увидеть чье-либо решение этой проблемы, но если нет более простого пути, вот как я реализовал его трудным способом:

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, но меньше одного или меньше нуля, но больше отрицательного одного случая, или уклон больше одного или меньшеотрицательный случайВсе, что вам нужно сделать, это нарисовать петлю линии вместо треугольника между каждым набором точек, и у вас будет незаполненное поле.

0 голосов
/ 14 декабря 2013

обходной путь: вместо рисования прямоугольника нарисуйте линию, но установите ширину обводки для краски.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...