Compare commits
6 Commits
51-als-geb
...
35-als-geb
Author | SHA1 | Date | |
---|---|---|---|
|
13fca50d6f | ||
|
7442d1fca4 | ||
|
cfcbe7d51c | ||
|
3edab82535 | ||
|
3fe90ce547 | ||
|
59c374eb02 |
2
code/src/Fitbot/.gitignore
vendored
2
code/src/Fitbot/.gitignore
vendored
@@ -13,3 +13,5 @@
|
|||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
|
.idea
|
||||||
|
.vscode
|
@@ -35,7 +35,11 @@ dependencies {
|
|||||||
implementation 'com.android.support:cardview-v7:28.0.0'
|
implementation 'com.android.support:cardview-v7:28.0.0'
|
||||||
implementation 'com.android.support:design:28.0.0'
|
implementation 'com.android.support:design:28.0.0'
|
||||||
implementation 'org.joml:joml:1.10.5'
|
implementation 'org.joml:joml:1.10.5'
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
implementation 'com.aldebaran:qisdk:1.7.5'
|
implementation 'com.aldebaran:qisdk:1.7.5'
|
||||||
|
@@ -15,6 +15,9 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Fitbot" >
|
android:theme="@style/Theme.Fitbot" >
|
||||||
|
<activity
|
||||||
|
android:name=".ui.activities.FitnessActivity"
|
||||||
|
android:exported="true" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activities.MainActivity"
|
android:name=".ui.activities.MainActivity"
|
||||||
android:exported="true" >
|
android:exported="true" >
|
||||||
|
@@ -0,0 +1,104 @@
|
|||||||
|
package com.example.fitbot.exercise;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
|
import com.example.fitbot.util.server.IWebSocketHandler;
|
||||||
|
import com.example.fitbot.util.server.WebSocket;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class AbstractExercise implements IWebSocketHandler {
|
||||||
|
|
||||||
|
private EMuscleGroup muscleGroup;
|
||||||
|
private GesturePath path;
|
||||||
|
|
||||||
|
// Static fields.
|
||||||
|
private static WebSocket webSocket;
|
||||||
|
private static AbstractExercise currentExercise = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the AbstractExercise class.
|
||||||
|
*
|
||||||
|
* @param muscleGroup The muscle group of the exercise.
|
||||||
|
* @param path The path of the exercise.
|
||||||
|
*/
|
||||||
|
public AbstractExercise(EMuscleGroup muscleGroup, GesturePath path) {
|
||||||
|
this.muscleGroup = muscleGroup;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the exercise.
|
||||||
|
* This method starts a WebSocket server
|
||||||
|
*/
|
||||||
|
public final void startExercise() {
|
||||||
|
|
||||||
|
// Ensure no other exercise is active.
|
||||||
|
if (currentExercise != null && currentExercise != this) {
|
||||||
|
currentExercise.__stopExercise();
|
||||||
|
Log.i("Exercises", "Another exercise was started when another was still running.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a WebSocket server is already running, change the event handler to be this class.
|
||||||
|
if (webSocket != null && webSocket.isConnected()) {
|
||||||
|
webSocket.setEventHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
webSocket = WebSocket.createServer();
|
||||||
|
Objects.requireNonNull(webSocket, "WebSocket server could not be created.");
|
||||||
|
|
||||||
|
webSocket.startListening();
|
||||||
|
webSocket.setEventHandler(this);
|
||||||
|
currentExercise = this;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for ending this exercise and returning the grade of the performance
|
||||||
|
* of this activity.
|
||||||
|
*/
|
||||||
|
public final double finishExercise() {
|
||||||
|
this.__stopExercise();
|
||||||
|
|
||||||
|
// TODO: Implement grade calculation
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the exercise.
|
||||||
|
* This method stops the WebSocket server.
|
||||||
|
*/
|
||||||
|
private void __stopExercise() {
|
||||||
|
if (webSocket != null && webSocket.isConnected()) {
|
||||||
|
webSocket.stop();
|
||||||
|
webSocket = null;
|
||||||
|
}
|
||||||
|
currentExercise = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current exercise is the current activity.
|
||||||
|
*/
|
||||||
|
public final boolean isCurrentActivity() {
|
||||||
|
return currentExercise == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the muscle group of the exercise.
|
||||||
|
*/
|
||||||
|
public EMuscleGroup getMuscleGroup() {
|
||||||
|
return muscleGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path of the exercise.
|
||||||
|
*/
|
||||||
|
public GesturePath getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
package com.example.fitbot.exercise;
|
||||||
|
|
||||||
|
public enum EMuscleGroup {
|
||||||
|
// TODO: Implement
|
||||||
|
|
||||||
|
TORSO(0),
|
||||||
|
ARMS(1),
|
||||||
|
LEGS(2),
|
||||||
|
BALANCE(3);
|
||||||
|
|
||||||
|
int muscleGroupIdentifier;
|
||||||
|
|
||||||
|
EMuscleGroup(int identifier) {
|
||||||
|
this.muscleGroupIdentifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIdentifier() {
|
||||||
|
return this.muscleGroupIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EMuscleGroup parse(int identifier) {
|
||||||
|
for (EMuscleGroup muscleGroup : EMuscleGroup.values()) {
|
||||||
|
if (muscleGroup.getIdentifier() == identifier) {
|
||||||
|
return muscleGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
package com.example.fitbot.exercise;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ExerciseUser class represents a user of the exercise application.
|
||||||
|
* This contains all necessary information of the current user.
|
||||||
|
*/
|
||||||
|
public class ExerciseUser {
|
||||||
|
|
||||||
|
public float upperArmLength;
|
||||||
|
public float lowerArmLength;
|
||||||
|
public float upperLegLength;
|
||||||
|
public float lowerLegLength;
|
||||||
|
public float height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the ExerciseUser class.
|
||||||
|
* @param upperArmLength The length of the upper arm.
|
||||||
|
* @param lowerArmLength The length of the lower arm.
|
||||||
|
* @param height The height of the user.
|
||||||
|
* @param upperLegLength The length of the upper leg.
|
||||||
|
* @param lowerLegLength The length of the lower leg.
|
||||||
|
*/
|
||||||
|
public ExerciseUser(float upperArmLength, float lowerArmLength, float height, float upperLegLength, float lowerLegLength) {
|
||||||
|
this.upperArmLength = upperArmLength;
|
||||||
|
this.lowerArmLength = lowerArmLength;
|
||||||
|
this.upperLegLength = upperLegLength;
|
||||||
|
this.lowerLegLength = lowerLegLength;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the ExerciseUser class.
|
||||||
|
* @param height The height of the user.
|
||||||
|
*/
|
||||||
|
public ExerciseUser(float height) {
|
||||||
|
this.height = height;
|
||||||
|
this.upperArmLength = height * 0.2f;
|
||||||
|
this.lowerArmLength = height * 0.2f;
|
||||||
|
this.upperLegLength = height * 0.3f;
|
||||||
|
this.lowerLegLength = height * 0.3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for the ExerciseUser class.
|
||||||
|
* This sets the default height to 180.0f. (1.80m)
|
||||||
|
*/
|
||||||
|
public ExerciseUser() {
|
||||||
|
this(180.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,113 @@
|
|||||||
|
package com.example.fitbot.exercise;
|
||||||
|
|
||||||
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
public class FitnessManager {
|
||||||
|
|
||||||
|
private static final String HOST_ADDRESS = "http://145.92.8.132";
|
||||||
|
|
||||||
|
private static final String PROPERTY_DESC = "description";
|
||||||
|
private static final String PROPERTY_VECTORS = "vector_data";
|
||||||
|
private static final String PROPERTY_NAME = "name";
|
||||||
|
private static final String PROPERTY_MUSCLE_GROUP = "muscle_group";
|
||||||
|
|
||||||
|
private static String sendHTTP(String url, String method, String contentType, String body) {
|
||||||
|
try {
|
||||||
|
URLConnection connection = new URL(url).openConnection();
|
||||||
|
connection.addRequestProperty("Content-Type", contentType);
|
||||||
|
connection.addRequestProperty("Request-Method", method);
|
||||||
|
connection.getOutputStream().write(body.getBytes());
|
||||||
|
connection.connect();
|
||||||
|
InputStream stream = connection.getInputStream();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
builder.append(line);
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for retrieving an exercise from the Raspberry Pi Database.
|
||||||
|
*
|
||||||
|
* @param uniqueIdentifier The unique identifier of the exercise
|
||||||
|
* @return The exercise, if it exists on the server. Otherwise null.
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractExercise> AbstractExercise acquireExercise(String uniqueIdentifier, Class<T> referenceClass) {
|
||||||
|
String response = sendHTTP(
|
||||||
|
HOST_ADDRESS + "/acquire", "GET", "application/json", "{\"kind\":\"" + uniqueIdentifier + "\"}"
|
||||||
|
);
|
||||||
|
// Validate the response
|
||||||
|
if (response != null) {
|
||||||
|
try {
|
||||||
|
JsonObject content = JsonParser.parseString(response).getAsJsonObject();
|
||||||
|
Constructor<T> constructor = referenceClass.getConstructor(referenceClass);
|
||||||
|
T instance = null;
|
||||||
|
try {
|
||||||
|
instance = constructor.newInstance(
|
||||||
|
EMuscleGroup.parse(content.get(PROPERTY_MUSCLE_GROUP).getAsInt()),
|
||||||
|
gesturePathFromString(content.get(PROPERTY_VECTORS).getAsString())
|
||||||
|
);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function for converting a string to a GesturePath object.
|
||||||
|
* The input string bytes will be directly converted into 3d vectors.
|
||||||
|
* Every coordinate is composed of 32 bits, so four characters per coordinate.
|
||||||
|
*
|
||||||
|
* @param input The string to convert
|
||||||
|
* @return The GesturePath object
|
||||||
|
*/
|
||||||
|
private static GesturePath gesturePathFromString(String input) {
|
||||||
|
byte[] bytes = input.getBytes();
|
||||||
|
|
||||||
|
// Check if the input string contains a valid amount of bytes (12 bytes per vector)
|
||||||
|
if (input.length() % 12 != 0) {
|
||||||
|
throw new IllegalArgumentException("Invalid input string length");
|
||||||
|
}
|
||||||
|
GesturePath.Builder builder = new GesturePath.Builder();
|
||||||
|
|
||||||
|
float[] xyz = new float[3];
|
||||||
|
for (int i = 0; i < bytes.length; i += 12) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
xyz[j] = Float.intBitsToFloat(
|
||||||
|
(bytes[i + j * 4] & 0xFF) << 24 |
|
||||||
|
(bytes[i + j * 4 + 1] & 0xFF) << 16 |
|
||||||
|
(bytes[i + j * 4 + 2] & 0xFF) << 8 |
|
||||||
|
(bytes[i + j * 4 + 3] & 0xFF)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
builder.addVector(new Vector3f(
|
||||||
|
xyz[0], xyz[1], xyz[2]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,18 +0,0 @@
|
|||||||
package com.example.fitbot.sports;
|
|
||||||
|
|
||||||
public enum ESportType {
|
|
||||||
|
|
||||||
FITNESS("Fitness"),
|
|
||||||
POWER("Krachttrening");
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
ESportType(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,6 +1,7 @@
|
|||||||
package com.example.fitbot.ui.activities;
|
package com.example.fitbot.ui.activities;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.NavigationView;
|
import android.support.design.widget.NavigationView;
|
||||||
import android.support.v4.view.GravityCompat;
|
import android.support.v4.view.GravityCompat;
|
||||||
@@ -8,6 +9,8 @@ import android.support.v4.widget.DrawerLayout;
|
|||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
import com.example.fitbot.R;
|
import com.example.fitbot.R;
|
||||||
|
|
||||||
@@ -17,17 +20,26 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
DrawerLayout drawerLayout;
|
DrawerLayout drawerLayout;
|
||||||
NavigationView navigationView;
|
NavigationView navigationView;
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
|
Button startButton;
|
||||||
|
|
||||||
@SuppressLint("WrongViewCast")
|
@SuppressLint("WrongViewCast")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate (Bundle savedInstanceState) {
|
protected void onCreate (Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main );
|
||||||
|
|
||||||
/*---Hooks---*/
|
/*---Hooks---*/
|
||||||
drawerLayout = findViewById(R.id.drawer_layout);
|
drawerLayout = findViewById(R.id.drawer_layout);
|
||||||
navigationView = findViewById(R.id.nav_view);
|
navigationView = findViewById(R.id.nav_view);
|
||||||
toolbar = findViewById(R.id.toolbar);
|
toolbar = findViewById(R.id.toolbar);
|
||||||
|
startButton = findViewById(R.id.startButton);
|
||||||
|
|
||||||
|
startButton.setOnClickListener(v -> {
|
||||||
|
// Switch to fitness activity
|
||||||
|
Log.i("MainActivity", "Switching to FitnessActivity");
|
||||||
|
Intent intent = new Intent(MainActivity.this, FitnessActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
|
||||||
/*---Tool Bar---*/
|
/*---Tool Bar---*/
|
||||||
// setSupportActionBar(toolbar);
|
// setSupportActionBar(toolbar);
|
||||||
|
@@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.example.fitbot.util.path.GesturePath;
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
@@ -24,6 +25,8 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
private Path referencePath, performingPath;
|
private Path referencePath, performingPath;
|
||||||
private Paint referencePaint, performingPaint;
|
private Paint referencePaint, performingPaint;
|
||||||
|
|
||||||
|
private Paint backgroundColor = new Paint();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants for the preview path projection.
|
* Constants for the preview path projection.
|
||||||
*/
|
*/
|
||||||
@@ -42,6 +45,9 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
*/
|
*/
|
||||||
public PersonalMotionPreviewElement(Context context, GesturePath path) {
|
public PersonalMotionPreviewElement(Context context, GesturePath path) {
|
||||||
super(context);
|
super(context);
|
||||||
|
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
|
||||||
|
this.backgroundColor = new Paint();
|
||||||
|
this.backgroundColor.setColor(0xFF000000); // Black
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.motionProcessor = new MotionProcessor();
|
this.motionProcessor = new MotionProcessor();
|
||||||
this.motionProcessor.startListening();
|
this.motionProcessor.startListening();
|
||||||
@@ -158,6 +164,7 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDraw(Canvas canvas) {
|
public void onDraw(Canvas canvas) {
|
||||||
|
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundColor);
|
||||||
// Draw the sport preview canvas
|
// Draw the sport preview canvas
|
||||||
canvas.drawPath(referencePath, referencePaint);
|
canvas.drawPath(referencePath, referencePaint);
|
||||||
canvas.drawPath(performingPath, performingPaint);
|
canvas.drawPath(performingPath, performingPaint);
|
||||||
|
@@ -10,7 +10,6 @@ public class GesturePath {
|
|||||||
|
|
||||||
// The vectors that make up the path.
|
// The vectors that make up the path.
|
||||||
private final PathSegment[] segments;
|
private final PathSegment[] segments;
|
||||||
private double curvature;
|
|
||||||
|
|
||||||
public GesturePath(Vector3f[] vectors) {
|
public GesturePath(Vector3f[] vectors) {
|
||||||
this(vectors, 0.0D);
|
this(vectors, 0.0D);
|
||||||
@@ -27,7 +26,6 @@ public class GesturePath {
|
|||||||
if ( vectors.length < 2)
|
if ( vectors.length < 2)
|
||||||
throw new IllegalArgumentException("A path must have at least two points.");
|
throw new IllegalArgumentException("A path must have at least two points.");
|
||||||
|
|
||||||
this.curvature = curvature;
|
|
||||||
this.segments = new PathSegment[vectors.length - 1];
|
this.segments = new PathSegment[vectors.length - 1];
|
||||||
for ( int i = 0; i < vectors.length - 1; i++)
|
for ( int i = 0; i < vectors.length - 1; i++)
|
||||||
segments[i] = new PathSegment(vectors[i], vectors[i + 1]);
|
segments[i] = new PathSegment(vectors[i], vectors[i + 1]);
|
||||||
@@ -39,7 +37,6 @@ public class GesturePath {
|
|||||||
*/
|
*/
|
||||||
public GesturePath(PathSegment... segments) {
|
public GesturePath(PathSegment... segments) {
|
||||||
this.segments = segments;
|
this.segments = segments;
|
||||||
this.curvature = 0.0d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -25,10 +25,9 @@ public class PathSegment {
|
|||||||
* depending on the curvature of the curve. If the curvature is unset, or set to 0
|
* depending on the curvature of the curve. If the curvature is unset, or set to 0
|
||||||
* then this method will use linear interpolation. Otherwise, it will use a curve.
|
* then this method will use linear interpolation. Otherwise, it will use a curve.
|
||||||
*
|
*
|
||||||
* @param dst The destination vector to interpolate to.
|
|
||||||
* @param t The interpolation value between 0 and 1.
|
* @param t The interpolation value between 0 and 1.
|
||||||
*/
|
*/
|
||||||
public Vector3f interpolate(Vector3f dst, double t) {
|
public Vector3f interpolate(double t) {
|
||||||
return new Vector3f(this.start)
|
return new Vector3f(this.start)
|
||||||
.lerp(this.end, (float) Math.min(1.0F, Math.max(0.0F, t)));
|
.lerp(this.end, (float) Math.min(1.0F, Math.max(0.0F, t)));
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#232323"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
tools:context=".ui.activities.FitnessActivity"
|
||||||
|
tools:openDrawer="start">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
|
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
|
||||||
|
android:id="@+id/personalMotionPreviewElement"
|
||||||
|
android:visibility="visible"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</android.support.v4.widget.DrawerLayout>
|
@@ -0,0 +1,37 @@
|
|||||||
|
package com.example.fitbot;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
|
import com.example.fitbot.util.path.PathSegment;
|
||||||
|
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PathSegmentTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPathSegment() {
|
||||||
|
// Test the PathSegment class
|
||||||
|
Vector3f[] vectors = new Vector3f[2];
|
||||||
|
vectors[0] = new Vector3f(0, 0, 0);
|
||||||
|
vectors[1] = new Vector3f(1, 1, 1);
|
||||||
|
GesturePath path = new GesturePath(vectors);
|
||||||
|
PathSegment[] segments = path.getSegments();
|
||||||
|
assertEquals(1, segments.length);
|
||||||
|
assertEquals(new Vector3f(0, 0, 0), segments[0].getStart());
|
||||||
|
assertEquals(new Vector3f(1, 1, 1), segments[0].getEnd());
|
||||||
|
assertEquals(new Vector3f(0.5f, 0.5f, 0.5f), segments[0].interpolate(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_pathSegmentInterpolation() {
|
||||||
|
Vector3f start = new Vector3f(0, 0, 0);
|
||||||
|
Vector3f end = new Vector3f(1, 1, 1);
|
||||||
|
PathSegment segment = new PathSegment(start, end);
|
||||||
|
assertEquals(new Vector3f(0.5f, 0.5f, 0.5f), segment.interpolate(0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user