Android AR Компас Дисплей - PullRequest
1 голос
/ 24 июля 2011

Я работаю над приложением дополненной реальности (AR) для телефона Android.Я хотел бы отобразить данные о своей ориентации в виде двух вращающихся осей: одна в верхней части экрана, чтобы показать текущий азимут (север, восток, юг, запад), и одна сбоку, чтобы показать высоту / высоту.Я новичок в программировании на Android, поэтому я не совсем уверен, как создать эти оси визуально.

Первой моей мыслью было, что я мог бы использовать предопределенные изображения, которые каким-то образом оборачиваются при попадании на краяэкран (как будто изображение было снаружи вращающегося цилиндра).Отсюда было бы просто сопоставить изображение с информацией, которую я извлекаю из датчиков.

Есть ли способ обернуть изображения, чтобы их можно было вращать в виртуальной плоскости в этомманера?Кто-нибудь может предложить лучшее решение моей первоначальной проблемы?

1 Ответ

0 голосов
/ 27 июля 2011

У меня не хватает времени, поэтому я нашел жестко запрограммированное решение, которое, вероятно, можно было бы распространить на более общий случай без особых проблем.Чтобы создать оси, я программно генерирую кучу объектов Path и затем рисую их на холсте.Затем я просто перевожу холст туда и обратно на основе значений азимута, которые я собираю.

Вот копия класса, который я использую для генерации оси азимута:

class AzimuthOverlay extends View {

// Values hardcoded for fullscreen landscape
// Width = 800 pixels

int tickPixels = 40; // Number of pixels between tick marks
final int MAJORTICKS = 36;
final int MINORTICKS = 36;

// Need additional 10 for proper wrapping
final int TOTALOBJECTS = MAJORTICKS + MINORTICKS + 10;

public double mAzimuth; // Set externally by a SensorEventListener class

private Paint ticPaint = new Paint();
private Paint numPaint = new Paint();
private ArrayList<Path> axis = new ArrayList<Path>(TOTALOBJECTS);

public AzimuthOverlay(Context context) {
    super(context);

    ticPaint.setAntiAlias(true);
    ticPaint.setColor(Color.GREEN);
    ticPaint.setStyle(Paint.Style.FILL);

    numPaint.setColor(Color.GREEN);
    numPaint.setStyle(Paint.Style.STROKE);
    numPaint.setStrokeWidth(2);

    // Extend to the left of the screen
    for (int i = -10; i < 0; i++) {
        if (i % 2 == 0) {
            axis.add(getMajorTick(i * tickPixels));
        }
        else {
            axis.add(getNumber(360 + 5*i, i * tickPixels));
        }
    }

    // Create axis (numbers on minor ticks)
    for (int i = 0; i < TOTALOBJECTS; i++) {
        if (i % 2 == 0) {
            axis.add(getMajorTick(i * tickPixels));
        }
        else {
            axis.add(getNumber((5*i)%360, i * tickPixels));
        }
    }


}

@Override
protected void onDraw(Canvas canvas) {

    canvas.translate((int)-mAzimuth * 8, 0); // 8 pixels per degree

    boolean toggle = true;  // Alternate between ticks and numbers
    for (Path p : axis) {
        if (toggle) {
            canvas.drawPath(p, ticPaint);
        }
        else {
            canvas.drawPath(p, numPaint);
        }
        toggle = (toggle == false) ? true : false;
    }

    super.onDraw(canvas);
}

// Create big tick marks as Path object
private Path getMajorTick(int offset) {
    Path mypath = new Path();

    mypath.moveTo(-2 + offset, 0);
    mypath.lineTo(-2 + offset, 20);
    mypath.lineTo(2 + offset, 20);
    mypath.lineTo(2 + offset, 0);
    mypath.close();

    return mypath;
}

// Create small tick marks as Path object
private Path getMinorTick(int offset) {
    Path mypath = new Path();

    mypath.moveTo(-2 + offset, 0);
    mypath.lineTo(-2 + offset, 10);
    mypath.lineTo(2 + offset, 10);
    mypath.lineTo(2 + offset, 0);
    mypath.close();

    return mypath;
}

// Create individual digits as Path object
private Path getDigit(int digit, int offset) {
    Path mypath = new Path();

    final int lx = -6;
    final int mx = 0;
    final int rx = 6;
    final int ty = 0;
    final int my = 6;
    final int by = 12;

    final int doffset = 2;

    switch(digit) {
    case 0:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.close();
        break;
    case 1:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(mx + offset, ty + doffset);
        mypath.lineTo(mx + offset, by + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        break;
    case 2:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        mypath.lineTo(lx + offset, my + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        break;
    case 3:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.moveTo(lx + offset, my + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        break;
    case 4:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(lx + offset, my + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        break;
    case 5:
        mypath.moveTo(rx + offset, ty + doffset);
        mypath.lineTo(lx + offset, ty + doffset);
        mypath.lineTo(lx + offset, my + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        break;
    case 6:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        mypath.lineTo(lx + offset, my + doffset);
        break;
    case 7:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        break;
    case 8:
        mypath.moveTo(lx + offset, ty + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(rx + offset, by + doffset);
        mypath.lineTo(lx + offset, by + doffset);
        mypath.lineTo(lx + offset, ty + doffset);
        mypath.moveTo(lx + offset, my + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        break;
    case 9:
        mypath.moveTo(rx + offset, by + doffset);
        mypath.lineTo(rx + offset, ty + doffset);
        mypath.lineTo(lx + offset, ty + doffset);
        mypath.lineTo(lx + offset, my + doffset);
        mypath.lineTo(rx + offset, my + doffset);
        break;
    }

    return mypath;
}

// Create a number up to 3 digits as a Path object
private Path getNumber(int number, int offset) {
    Path mypath = new Path();

    final int digitoffset = 7;

    int digit;
    int temp;
    if (number > 99) { // 3-digit number
        digit = number / 100;
        mypath = getDigit(digit, offset - 2*digitoffset);
        temp = (number % 100);
        digit = temp / 10;
        mypath.addPath(getDigit(digit, offset));
        digit = temp % 10;
        mypath.addPath(getDigit(digit, offset + 2*digitoffset));
    }
    else if (number > 9) { // 2-digit number
        digit = number / 10;
        mypath = getDigit(digit, offset-digitoffset);
        mypath.addPath(getDigit(number % 10, offset+digitoffset));
    }
    else { // 1-digit number
        mypath = getDigit(number, offset);
    }

    return mypath;
}

protected void setAzimuth(double azimuth) {
    mAzimuth = azimuth;
}   

}

...