我正在为Android手机开发增强现实(AR)应用程序。我希望以两个旋转轴的形式显示我的方向数据:一个位于屏幕顶部以显示当前方位角(北,东,南,西),另一个用于显示海拔高度。我是Android编程的新手,所以我不确定如何在视觉上创建这些轴。
我的第一个想法是,我可以使用预定义的图像,以某种方式环绕屏幕的边缘(就像图像在旋转圆柱的外面)。从这里开始,将图像与我从传感器中拉出的信息排成一行就很简单了。
是否有某种方法来包装图像,以便它们可以以这种方式在虚拟平面中旋转?任何人都能建议更好地解决我原来的问题吗?
答案 0 :(得分:0)
我时间紧迫,所以我提出了一个硬编码的解决方案,可能会扩展到更一般的情况而不会有太多麻烦。为了创建轴,我以编程方式生成一堆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;
}
}