目前我正在使用Git-hub库为基于AR位置的项目制作演示应用程序。我正在使用AR-Location Based Android。图书馆在纵向模式下工作正常,但在横向模式下,Ar点来自屏幕底部(如从底部出来的气泡)并隐藏到屏幕顶部,同时旋转相机。我也在Git中提出了问题,但是所有者没有回应。我试图解决它,但无法做到。任何人都可以指导我解决问题。或者在哪里改变。
我认为这些课程负责以肖像和横向模式进行投影。如果没有,请告诉我在哪里改变。
@SuppressLint("ViewConstructor")
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.KITKAT)
public class ARCamera extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "ARCamera";
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.Size previewSize;
List<Camera.Size> supportedPreviewSizes;
Camera camera;
Camera.Parameters parameters;
Activity activity;
float[] projectionMatrix = new float[16];
int cameraWidth;
int cameraHeight;
private final static float Z_NEAR = 0.5f; //Increase or decrease distance, between poines
private final static float Z_FAR = 2000;
public ARCamera(Context context, SurfaceView surfaceView) {
super(context);
this.surfaceView = surfaceView;
this.activity = (Activity) context;
surfaceHolder = this.surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
this.camera = camera;
if (this.camera != null) {
supportedPreviewSizes = this.camera.getParameters().getSupportedPreviewSizes();
requestLayout();
Camera.Parameters params = this.camera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
this.camera.setParameters(params);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (supportedPreviewSizes != null) {
previewSize = getOptimalPreviewSize(supportedPreviewSizes, width, height);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (previewSize != null) {
previewWidth = previewSize.width;
previewHeight = previewSize.height;
}
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (camera != null) {
parameters = camera.getParameters();
int orientation = getCameraOrientation();
camera.setDisplayOrientation(orientation);
camera.getParameters().setRotation(orientation);
camera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
private int getCameraOrientation() {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Toast.makeText(activity, "Rotation = " + rotation, Toast.LENGTH_SHORT).show();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
Toast.makeText(activity, "Degrees = " + degrees, Toast.LENGTH_SHORT).show();
break;
case Surface.ROTATION_90:
degrees = 90;
Toast.makeText(activity, "Degrees = " + degrees, Toast.LENGTH_SHORT).show();
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int orientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
orientation = (info.orientation + degrees) % 360;
orientation = (360 - orientation) % 360;
} else {
orientation = (info.orientation - degrees + 360) % 360;
}
return orientation;
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) width / height;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
if (optimalSize == null) {
optimalSize = sizes.get(0);
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (camera != null) {
this.cameraWidth = width;
this.cameraHeight = height;
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(previewSize.width, previewSize.height);
requestLayout();
try {
camera.setParameters(params);
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
generateProjectionMatrix();
}
}
private void generateProjectionMatrix() {
float ratio = (float) this.cameraWidth / this.cameraHeight;
final int OFFSET = 0;
final float LEFT = -ratio;
final float RIGHT = ratio;
final float BOTTOM = -1; //increases the speed of points going
final float TOP = 1; //increases the speed of points coming
Matrix.frustumM(projectionMatrix, OFFSET, LEFT, RIGHT, BOTTOM, TOP, Z_NEAR, Z_FAR);
}
public float[] getProjectionMatrix() {
return projectionMatrix;
}
}
活动类
public class ARActivity extends AppCompatActivity implements SensorEventListener, LocationListener {
final static String TAG = "ARActivity";
private SurfaceView surfaceView;
private FrameLayout cameraContainerLayout;
private AROverlayView arOverlayView;
private Camera camera;
private ARCamera arCamera;
private TextView tvCurrentLocation;
private SensorManager sensorManager;
private final static int REQUEST_CAMERA_PERMISSIONS_CODE = 11;
public static final int REQUEST_LOCATION_PERMISSIONS_CODE = 0;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters
private static final long MIN_TIME_BW_UPDATES = 0;//1000 * 60 * 1; // 1 minute
private LocationManager locationManager;
public Location location;
boolean isGPSEnabled;
boolean isNetworkEnabled;
boolean locationServiceAvailable;
private DisplayMetrics metrics;
private RelativeLayout infoLayout;
private ImageView appLogo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ar);
Utility.getFullScreenView(this);
sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
cameraContainerLayout = (FrameLayout) findViewById(R.id.camera_container_layout);
surfaceView = (SurfaceView) findViewById(R.id.surface_view);
tvCurrentLocation = (TextView) findViewById(R.id.tv_current_location);
infoLayout = (RelativeLayout) findViewById(R.id.info_layout);
appLogo = (ImageView) findViewById(R.id.logoApp);
arOverlayView = new AROverlayView(this);
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
infoLayout.getLayoutParams().width = metrics.widthPixels/4;
appLogo.getLayoutParams().width = metrics.widthPixels/5;
appLogo.getLayoutParams().height = metrics.heightPixels/4;
}
@Override
public void onResume() {
super.onResume();
requestLocationPermission();
requestCameraPermission();
registerSensors();
initAROverlayView();
}
@Override
public void onPause() {
releaseCamera();
super.onPause();
}
public void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSIONS_CODE);
} else {
initARCameraView();
}
}
public void requestLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSIONS_CODE);
} else {
initLocationService();
}
}
public void initAROverlayView() {
if (arOverlayView.getParent() != null) {
((ViewGroup) arOverlayView.getParent()).removeView(arOverlayView);
}
cameraContainerLayout.addView(arOverlayView);
}
public void initARCameraView() {
reloadSurfaceView();
if (arCamera == null) {
arCamera = new ARCamera(this, surfaceView);
}
if (arCamera.getParent() != null) {
((ViewGroup) arCamera.getParent()).removeView(arCamera);
}
cameraContainerLayout.addView(arCamera);
arCamera.setKeepScreenOn(true);
initCamera();
}
private void initCamera() {
int numCams = Camera.getNumberOfCameras();
if(numCams > 0){
try{
camera = Camera.open();
camera.startPreview();
arCamera.setCamera(camera);
} catch (RuntimeException ex){
Toast.makeText(this, "Camera not found", Toast.LENGTH_LONG).show();
}
}
}
private void reloadSurfaceView() {
if (surfaceView.getParent() != null) {
((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
}
cameraContainerLayout.addView(surfaceView);
}
private void releaseCamera() {
if(camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
arCamera.setCamera(null);
camera.release();
camera = null;
}
}
private void registerSensors() {
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
float[] rotationMatrixFromVector = new float[16];
float[] projectionMatrix = new float[16];
float[] rotatedProjectionMatrix = new float[16];
SensorManager.getRotationMatrixFromVector(rotationMatrixFromVector, sensorEvent.values);
if (arCamera != null) {
projectionMatrix = arCamera.getProjectionMatrix();
}
Matrix.multiplyMM(rotatedProjectionMatrix, 0, projectionMatrix, 0, rotationMatrixFromVector, 0);
this.arOverlayView.updateRotatedProjectionMatrix(rotatedProjectionMatrix);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
//do nothing
}
private void initLocationService() {
if ( Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
return ;
}
try {
this.locationManager = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
// Get GPS and network status
this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isNetworkEnabled && !isGPSEnabled) {
// cannot get location
this.locationServiceAvailable = false;
}
this.locationServiceAvailable = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateLatestLocation();
}
}
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateLatestLocation();
}
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
private void updateLatestLocation() {
if (arOverlayView !=null && location != null) {
arOverlayView.updateCurrentLocation(location);
tvCurrentLocation.setText(String.format("lat: %s \nlon: %s \naltitude: %s \n",
location.getLatitude(), location.getLongitude(), location.getAltitude()));
}
}
@Override
public void onLocationChanged(Location location) {
updateLatestLocation();
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
public void showHideInfo(View view) {
infoLayout.setVisibility(View.VISIBLE);
infoLayout.startAnimation(AnimationUtils.loadAnimation(this,R.anim.slide_in));
}
public void closeInfo(View view) {
infoLayout.setVisibility(View.GONE);
infoLayout.startAnimation(AnimationUtils.loadAnimation(this,android.R.anim.slide_out_right));
}
}
LocationHelper Class
public class LocationHelper {
private final static double WGS84_A = 6378137.0; // WGS 84 semi-major axis constant in meters
private final static double WGS84_E2 = 0.00669437999014; // square of WGS 84 eccentricity
public static float[] WSG84toECEF(Location location) {
double radLat = Math.toRadians(location.getLatitude());
double radLon = Math.toRadians(location.getLongitude());
float clat = (float) Math.cos(radLat);
float slat = (float) Math.sin(radLat);
float clon = (float) Math.cos(radLon);
float slon = (float) Math.sin(radLon);
float N = (float) (WGS84_A / Math.sqrt(1.0 - WGS84_E2 * slat * slat));
float x = (float) ((N + location.getAltitude()) * clat * clon);
float y = (float) ((N + location.getAltitude()) * clat * slon);
float z = (float) ((N * (1.0 - WGS84_E2) + location.getAltitude()) * slat);
return new float[] {x , y, z};
}
public static float[] ECEFtoENU(Location currentLocation, float[] ecefCurrentLocation, float[] ecefPOI) {
double radLat = Math.toRadians(currentLocation.getLatitude());
double radLon = Math.toRadians(currentLocation.getLongitude());
float clat = (float)Math.cos(radLat);
float slat = (float)Math.sin(radLat);
float clon = (float)Math.cos(radLon);
float slon = (float)Math.sin(radLon);
float dx = ecefCurrentLocation[0] - ecefPOI[0];
float dy = ecefCurrentLocation[1] - ecefPOI[1];
float dz = ecefCurrentLocation[2] - ecefPOI[2];
float east = -slon*dx + clon*dy;
float north = -slat*clon*dx - slat*slon*dy + clat*dz;
float up = clat*clon*dx + clat*slon*dy + slat*dz;
return new float[] {east , north, up, 1};
}
}
我认为前两个班负责。但我无法这样做。请指导我。