aboutsummaryrefslogtreecommitdiffhomepage
path: root/platform_tools/android/apps/skar_java/src/main/java/com/google/skar/examples/helloskar/app/SkARFingerPainting.java
blob: eac2a6bb33efa14fd85464573f3aa888367b32d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package com.google.skar.examples.helloskar.app;

import android.graphics.Color;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import java.util.ArrayList;

public class SkARFingerPainting {
    // Points obtained by touching the screen. The first point is always brough to (0,0).
    // All subsequent points are translated by the same amount.
    private ArrayList<PointF> points = new ArrayList<>();
    private ArrayList<Integer> jumpPoints = new ArrayList<>();
    private Map<Integer, Integer> indexColors = new HashMap<>();
    private Map<Path, Integer> pathColors = new HashMap<>();
    private ArrayList<Path> paths = new ArrayList<>();
    private int color = Color.RED;

    // Previous point added to the path. This points belongs to the path in local space.
    public PointF previousPoint;

    // Holds the model matrix of the first point added to such that the path can be drawn at the
    // model location (i.e on the Plane)
    private float[] modelMatrix;

    private boolean isSmooth;

    public SkARFingerPainting(boolean smooth) {
        this.isSmooth = smooth;
    }

    public boolean getSmoothness() {
        return isSmooth;
    }

    public void setSmoothness(boolean smooth) {
        isSmooth = smooth;
    }

    // Adds another point to the path in Local space
    public void addPoint(PointF p, boolean jumpPoint) {
        points.add(p);
        if (jumpPoint) {
            Log.i("Jumped!", Integer.toString(points.size() - 1));
            jumpPoints.add(points.size() - 1);
            indexColors.put(points.size() - 1, color);
        }
        previousPoint = p;
    }

    // Used to build a path before rendering it
    public void buildPath() {
        paths = new ArrayList<>();
        if (points.size() <= 1) {
            return;
        }


        if (isSmooth) {
            int start = 0;
            for (int j = 1; j < jumpPoints.size(); j++) {

                int finish = jumpPoints.get(j);
                buildSmoothFromTo(start, finish);
                start = finish;
            }

            buildSmoothFromTo(start, points.size());
        } else {

            int start = 0;
            for (int j = 1; j < jumpPoints.size(); j++) {
                int finish = jumpPoints.get(j);
                buildRoughFromTo(start, finish);
                start = finish;
            }

            buildRoughFromTo(start, points.size());
        }
    }

    private void buildRoughFromTo(int start, int finish) {
        Path p = new Path();
        int c = indexColors.get(start);
        p.moveTo(points.get(start).x, points.get(start).y);
        for (int i = start + 1; i < finish; i++) {
            p.lineTo(points.get(i).x, points.get(i).y);
        }
        paths.add(p);
        pathColors.put(p, c);
    }

    private void buildSmoothFromTo(int start, int finish) {
        Path p = new Path();
        int c = indexColors.get(start);
        int nbPts = finish - start;
        // If less than 3 points, than draw a line between the two points
        if (nbPts <= 2 && nbPts > 1) {
            p.moveTo(points.get(start).x, points.get(start).y);
            p.lineTo(points.get(start + 1).x, points.get(start + 1).y);
        } else if (nbPts >= 3){
            // Else, essentially run deCasteljau
            p.moveTo(points.get(start).x, points.get(start).y);
            p.lineTo((points.get(start).x + points.get(start + 1).x) / 2,
                     (points.get(start).y + points.get(start + 1).y) / 2);

            for (int i = start + 1; i < finish - 1; i++) {
                PointF p1 = points.get(i);
                PointF p2 = points.get(i + 1);
                p.quadTo(p1.x, p1.y, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
            }

            p.lineTo(points.get(finish - 1).x, points.get(finish - 1).y);
        }
        paths.add(p);
        pathColors.put(p, c);
    }

    public boolean isEmpty() {
        return points.isEmpty();
    }

    public float[] getModelMatrix() {
        return modelMatrix;
    }

    public void setModelMatrix(float[] m) {
        modelMatrix = m;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public int getPathColor(Path p) {
        return pathColors.get(p);
    }

    public ArrayList<Path> getPaths() {
        return paths;
    }

    public void reset() {
        points.clear();
        jumpPoints.clear();
        paths.clear();
        pathColors.clear();
        indexColors.clear();
    }
}