1

I am working on AR application and I am using ViroCore SDK. The question is how can I measure distance with help of ViroCore SDK? Should I do this by placing 2 object on surface and then work with with their coordinates or maybe there is another way to do this? Now I am trying to do something like described in this post https://stackoverflow.com/a/45987189/3071070

iCaesar
  • 421
  • 2
  • 10
  • 23

1 Answers1

4

This is my class for measure distance between two objects placed in AR:

public class ARRuler {

public static final String TAG = ARRuler.class.getSimpleName();

private static final long PROCESS_POINT_DELAY = 1500L;

private static final int BOX_COLOR = Color.parseColor("#FF0000");
private static final float BOX_WIDTH = 0.05f;
private static final float BOX_HEIGHT = 0.05f;
private static final float BOX_LENGTH = 0.05f;

private static final int DISTANCE_LABEL_HEIGHT = 100;
private static final int DISTANCE_LABEL_WIDTH = 100;
private static final int DISTANCE_LABEL_TEXT_COLOR = Color.parseColor("#FF0000");
private static final int DISTANCE_LABEL_TEXT_SIZE = 10;

private static final float POLYLINE_THICKNESS = 0.05f;
private static final int POLYLINE_COLOR = Color.parseColor("#FFFFFF");


private ViroViewARCore mViroViewARCore;
private ARScene mARScene;
private List<Node> mSelectedNodes;
private List<Float> mDistances;

public ARRuler(ViroViewARCore viroViewARCore, ARScene arScene) {
    this.mViroViewARCore = viroViewARCore;
    this.mARScene = arScene;
    this.mSelectedNodes = new ArrayList<>();
    this.mDistances = new ArrayList<>();
}

public void pointSelected(Vector position) {
    Log.d(TAG, "pointSelected: " + position);

    Box box = new Box(BOX_WIDTH, BOX_HEIGHT, BOX_LENGTH);

    Material material = new Material();
    material.setDiffuseColor(BOX_COLOR);
    box.setMaterials(Collections.singletonList(material));

    Node boxNode = new Node();
    boxNode.setGeometry(box);
    boxNode.setPosition(position);

    if (mSelectedNodes.size() == 0) {
        boxNode.setClickListener(new ClickListener() {
            @Override
            public void onClick(int i, Node node, Vector vector) {
                Log.d(TAG, "onClick: First point clicked");

               mSelectedNodes.add(node);
               startDelayedProcessing();
            }

            @Override
            public void onClickState(int i, Node node, ClickState clickState, Vector vector) {

            }
        });
    }

    mARScene.getRootNode().addChildNode(boxNode);
    mSelectedNodes.add(boxNode);

    startDelayedProcessing();
}

private void startDelayedProcessing() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            processSelectedPoints();
        }
    }, PROCESS_POINT_DELAY);
}

private void processSelectedPoints() {
    Log.d(TAG, "processSelectedPoints: ");

    if (mSelectedNodes.size() < 2) {
        Log.d(TAG, "processSelectedPoints: Only one point, return");
        return;
    }

    for (int i = 0; i < mSelectedNodes.size(); i++) {
        Log.d(TAG, "processSelectedPoints: Start looping...");

        if (i + 1 == mSelectedNodes.size()) {
            Log.d(TAG, "processSelectedPoints: Last pair reached, return");
            return;
        }

        Node start = mSelectedNodes.get(i);
        Node end = mSelectedNodes.get(i + 1);

        drawDistanceLabel(start, end);
        drawPolylines();
    }
}

private void drawDistanceLabel(Node start, Node end) {
    Vector startVector = start.getPositionRealtime();
    Vector endVector = end.getPositionRealtime();

    Log.d(TAG, "drawDistanceLabel: Vectors created!");
    Log.d(TAG, "drawDistanceLabel: startVector=" + startVector);
    Log.d(TAG, "drawDistanceLabel: endVector=" + endVector);

    float distance = startVector.distance(endVector);
    Log.d(TAG, "drawDistanceLabel: distance=" + distance);
    mDistances.add(distance);

    String distanceString = new DecimalFormat("#.###").format(distance);
    Log.d(TAG, "drawDistanceLabel: distanceString=" + distanceString);

    Text text = new Text(mViroViewARCore.getViroContext(), distanceString,
            DISTANCE_LABEL_WIDTH, DISTANCE_LABEL_HEIGHT);
    text.setColor(DISTANCE_LABEL_TEXT_COLOR);
    text.setFontSize(DISTANCE_LABEL_TEXT_SIZE);

    Node node = new Node();
    node.setGeometry(text);

    Vector labelPosition = startVector.midpoint(endVector);
    node.setPosition(labelPosition);

    mARScene.getRootNode().addChildNode(node);
}

private void drawPolylines() {
    Log.d(TAG, "drawPolylines: ");

    Polyline polyline = new Polyline(POLYLINE_THICKNESS);
    polyline.setPoints(getVectors());

    Material material = new Material();
    material.setDiffuseColor(POLYLINE_COLOR);
    polyline.setMaterials(Collections.singletonList(material));

    Node node = new Node();
    node.setGeometry(polyline);

    mARScene.getRootNode().addChildNode(node);
}

private List<Vector> getVectors() {
    Log.d(TAG, "getVectors: ");

    List<Vector> vectors = new ArrayList<>();

    for (Node node : mSelectedNodes) {
        vectors.add(node.getPositionRealtime());
    }

    return vectors;
}

}

It draws red box on clicked position, and after 2 boxes added it draws polyline and text label with distance between this boxes. To start using it you just need to copy it to your project and pass ViroViewARCore and ARScene objects. After this, just call ARRuler.pointSelected(selectedPosition) in your Node.ClickListener() callback.

Feel free to ask any questions.

iCaesar
  • 421
  • 2
  • 10
  • 23