dat-ng / ar-location-based-android

This AR app generally show where things are in the real-world by indicating where the app thinks they are over the camera view when the user holds the phone up and moves it about.
MIT License
203 stars 85 forks source link

Point Collision & add custom views instead of default circles (SOLUTIONS) #37

Open omerxhaferi opened 3 years ago

omerxhaferi commented 3 years ago

package ng.dat.ar;

import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.location.Location; import android.opengl.Matrix; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView;

import java.util.ArrayList; import java.util.List;

import ng.dat.ar.helper.LocationHelper; import ng.dat.ar.model.ARPoint;

/**

public class AROverlayView extends RelativeLayout {

private Context context;
private float[] rotatedProjectionMatrix = new float[16];
private Location currentLocation;
private final List<ARPoint> arPoints;
private final List<TextView> textViews;

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

    textViews = new ArrayList<>();

    this.context = context;
    this.setWillNotDraw(false);
    //Demo points
    arPoints = new ArrayList<ARPoint>() {{
        add(new ARPoint("New York", 40.7128, 74.0060, 50));
        add(new ARPoint("London", 51.5074, 0.1278, 100));
        add(new ARPoint("Frankfurn", 50.1109, 8.6821, 150));
        add(new ARPoint("Sydney", 33.8688, 151.2093, 200));
        add(new ARPoint("Rome", 41.9028, 12.4964, 250));
        add(new ARPoint("Athens", 37.9838, 23.7275, 300));
    }};

    for (int i = 0; i < arPoints.size(); i++) {

        textViews.add(new TextView(context));
        textViews.get(i).setTextSize(40);
        textViews.get(i).setBackgroundColor(Color.RED);
        this.addView(textViews.get(i));
    }
}

public void updateRotatedProjectionMatrix(float[] rotatedProjectionMatrix) {
    this.rotatedProjectionMatrix = rotatedProjectionMatrix;
    this.invalidate();
}

public void updateCurrentLocation(Location currentLocation) {
    this.currentLocation = currentLocation;
    this.invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (currentLocation == null) {
        return;
    }

    for (int i = 0; i < arPoints.size(); i++) {
        float[] currentLocationInECEF = LocationHelper.WSG84toECEF(currentLocation);
        float[] pointInECEF = LocationHelper.WSG84toECEF(arPoints.get(i).getLocation());
        float[] pointInENU = LocationHelper.ECEFtoENU(currentLocation, currentLocationInECEF, pointInECEF);

        float[] cameraCoordinateVector = new float[4];
        Matrix.multiplyMV(cameraCoordinateVector, 0, rotatedProjectionMatrix, 0, pointInENU, 0);

        // cameraCoordinateVector[2] is z, that always less than 0 to display on right position
        // if z > 0, the point will display on the opposite
        if (cameraCoordinateVector[2] < 0) {
            float x = (0.5f + cameraCoordinateVector[0] / cameraCoordinateVector[3]) * getWidth();
            float y = (0.5f - cameraCoordinateVector[1] / cameraCoordinateVector[3]) * getHeight();

            textViews.get(i).setX(x);
            textViews.get(i).setY(y);
            textViews.get(i).setText(arPoints.get(i).getName());
        }
    }
}

}

SmartToolFactory commented 3 years ago

Why Matrix.multiplyMV(cameraCoordinateVector, 0, rotatedProjectionMatrix, 0, pointInENU, 0); is required? What does it do?