Сравнение произвольных фигур (кривых)
Добавлено: 27 мар 2018, 00:22
Друзья, привет.
Подскажите, насколько сложно реализовать такую вещь как сравнение произвольных фигур (кривых)?
Суть в чём: хочу мышкой (пальцем, в дальнейшем несколькими пальцами) двигать курсор. Система запоминает траекторию движения (кривую, фигуру) и сверяет с образцом.
Например, повторите рисунок - кружок, треугольник и тд.
Как новичок, я разделил проблему на части:
1. Запись траектории движения курсора. Т.е. запись координат курсора каждый тик.
(Решена. Правда не знаю на сколько правильно. С помощью двух объектов List);
2. Настроить систему так, чтобы вне зависимости от скорости движения количество координат не менялось. Сейчас, если быстро провести, например, прямую, то допустим получится 10 точек. А если эту же прямую провести медленно, то и все 100 точек получится;
3. Найти алгоритм сравнения двух кривых/фигур, нарисованную пользователем с образцами.
В разделах алгебры, что-то есть похожее, но это для точного соответствия, а как реализовать похожесть? То ли каждую точку сравнивать, то ли отрезками, то ли ещё как, плюс учитывая коэффициент отклонения/погрешности/похожести.
Ниже код скрипта. Удалось пока только записывать координаты и после отпускания мышки система повторяет траекторию. Со спецэффектами)
Пример работы на текущем этапе.
[youtube]https://youtu.be/YU_zjFdPeg8[/youtube]
Подскажите, насколько сложно реализовать такую вещь как сравнение произвольных фигур (кривых)?
Суть в чём: хочу мышкой (пальцем, в дальнейшем несколькими пальцами) двигать курсор. Система запоминает траекторию движения (кривую, фигуру) и сверяет с образцом.
Например, повторите рисунок - кружок, треугольник и тд.
Как новичок, я разделил проблему на части:
1. Запись траектории движения курсора. Т.е. запись координат курсора каждый тик.
(Решена. Правда не знаю на сколько правильно. С помощью двух объектов List);
2. Настроить систему так, чтобы вне зависимости от скорости движения количество координат не менялось. Сейчас, если быстро провести, например, прямую, то допустим получится 10 точек. А если эту же прямую провести медленно, то и все 100 точек получится;
3. Найти алгоритм сравнения двух кривых/фигур, нарисованную пользователем с образцами.
В разделах алгебры, что-то есть похожее, но это для точного соответствия, а как реализовать похожесть? То ли каждую точку сравнивать, то ли отрезками, то ли ещё как, плюс учитывая коэффициент отклонения/погрешности/похожести.
Ниже код скрипта. Удалось пока только записывать координаты и после отпускания мышки система повторяет траекторию. Со спецэффектами)
Пример работы на текущем этапе.
[youtube]https://youtu.be/YU_zjFdPeg8[/youtube]
Синтаксис:
Используется csharp
// СХЕМА:
//1. Зажимаем мышку и двигаем курсором. Система записывает траекторию движения курсором.
//2. Отпускаем мышку. Система повторяет траекторию движения курсором.
//+ за курсором передвигается и объекты ТрайлРендерер (спецэффекты)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Swipe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
// Переменные для вывода текста на экран
public Text TextX;
public Text TextY;
// Переменные для хранения координат курсора мыши, т.е. запись траектории движения мыши после зажатия ЛКМ
List<float> listX = new List<float>();
List<float> listY = new List<float>();
public GameObject MouseFollow;
private GameObject inst_MyGO1;
private GameObject inst_MyGO2;
bool GoMove = false; // хранится флаг запуска повтора движения курсора
int i = -1;
public float distanceFromCamera = 5.0f;
private void OnMouseDown()
{
// ПРИ НАЖАТИИ НА МЫШЬ
if (GoMove)
{ }
else
{
// Повтор движения курсора мыши выключен
// Получим координату курсора
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
// Уничтожим объект существующий ТрайлРендерер, иначе будут клонироваться до бесконечности
Destroy(inst_MyGO2);
// Добавим новый ТрайлРендерер
inst_MyGO1 = Instantiate(MouseFollow, mouseScreenToWorld, Quaternion.identity) as GameObject;
GoMove = false;
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x + " - Начало";
TextY.text = "Y: " + mouseScreenToWorld.y + " - Начало";
// Добавим текущую координату в список
listX.Add(mouseScreenToWorld.x);
listY.Add(mouseScreenToWorld.y);
}
}
public void OnDrag(PointerEventData eventData)
{
//ДВИЖЕНИЕ МЫШИ ПРОДОЛЖАЕТСЯ
// Получаем координаты курсора мыши
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x;
TextY.text = "Y: " + mouseScreenToWorld.y;
// Добавим текущую координату в список
listX.Add(mouseScreenToWorld.x);
listY.Add(mouseScreenToWorld.y);
// Передвигаем объект ТрайРендерер (спецэффекты) туда где курсор мыши, т.е. следуем за мышью
inst_MyGO1.transform.position = new Vector3(mouseScreenToWorld.x, mouseScreenToWorld.y, distanceFromCamera);
}
public void OnEndDrag(PointerEventData eventData)
{
// ПРИ ОТПУСКАНИИ МЫШКИ
if (GoMove)
{
}
else
{
// Повтор движения курсора мыши выключен
// Получаем координаты курсора мыши
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x + " - Конец";
TextY.text = "Y: " + mouseScreenToWorld.y + " - Конец";
// Запускаем повтор движения курсора
GoMove = true;
//Уничтожаем объект ТрайлРендерер (спецэффекты), который следовал за курсором пользователя
Destroy(inst_MyGO1);
// СОздаём новый объект ТрайлРендерер (спецэффекты), который будет следовать за курсором повтора
inst_MyGO2 = Instantiate(MouseFollow, new Vector3(listX[0], listY[0], distanceFromCamera), Quaternion.identity) as GameObject;
}
}
void Start()
{
}
void Update()
{
// КАЖДЫЙ КАДР
if (GoMove)
{
// ПОВТОР ДВИЖЕНИЯ КУРСОРА ВКЛЮЧЁН, т.е. сейчас система сама повторяет траекторию движения курсора
// Увеличиваем счётчик
i++;
if (i < listX.Count)
{
// Текущий номер списка меньше, чем количество в списке координат
//Переместим объект ТрайлРендерер в следующую координату
inst_MyGO2.transform.position = new Vector3(listX[i], listY[i], distanceFromCamera);
}
else
{
//Все координаты пройдены, очистим списки координат и установим переменные в исходное положение
listX.Clear();
listY.Clear();
i = -1;
GoMove = false;
}
}
}
}
//1. Зажимаем мышку и двигаем курсором. Система записывает траекторию движения курсором.
//2. Отпускаем мышку. Система повторяет траекторию движения курсором.
//+ за курсором передвигается и объекты ТрайлРендерер (спецэффекты)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class Swipe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
// Переменные для вывода текста на экран
public Text TextX;
public Text TextY;
// Переменные для хранения координат курсора мыши, т.е. запись траектории движения мыши после зажатия ЛКМ
List<float> listX = new List<float>();
List<float> listY = new List<float>();
public GameObject MouseFollow;
private GameObject inst_MyGO1;
private GameObject inst_MyGO2;
bool GoMove = false; // хранится флаг запуска повтора движения курсора
int i = -1;
public float distanceFromCamera = 5.0f;
private void OnMouseDown()
{
// ПРИ НАЖАТИИ НА МЫШЬ
if (GoMove)
{ }
else
{
// Повтор движения курсора мыши выключен
// Получим координату курсора
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
// Уничтожим объект существующий ТрайлРендерер, иначе будут клонироваться до бесконечности
Destroy(inst_MyGO2);
// Добавим новый ТрайлРендерер
inst_MyGO1 = Instantiate(MouseFollow, mouseScreenToWorld, Quaternion.identity) as GameObject;
GoMove = false;
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x + " - Начало";
TextY.text = "Y: " + mouseScreenToWorld.y + " - Начало";
// Добавим текущую координату в список
listX.Add(mouseScreenToWorld.x);
listY.Add(mouseScreenToWorld.y);
}
}
public void OnDrag(PointerEventData eventData)
{
//ДВИЖЕНИЕ МЫШИ ПРОДОЛЖАЕТСЯ
// Получаем координаты курсора мыши
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x;
TextY.text = "Y: " + mouseScreenToWorld.y;
// Добавим текущую координату в список
listX.Add(mouseScreenToWorld.x);
listY.Add(mouseScreenToWorld.y);
// Передвигаем объект ТрайРендерер (спецэффекты) туда где курсор мыши, т.е. следуем за мышью
inst_MyGO1.transform.position = new Vector3(mouseScreenToWorld.x, mouseScreenToWorld.y, distanceFromCamera);
}
public void OnEndDrag(PointerEventData eventData)
{
// ПРИ ОТПУСКАНИИ МЫШКИ
if (GoMove)
{
}
else
{
// Повтор движения курсора мыши выключен
// Получаем координаты курсора мыши
Vector3 mousePosition = Input.mousePosition;
// Координаты по z устанавливаем как расстояние до камеры (хз зачем, но работает)
mousePosition.z = distanceFromCamera;
// Преобразуем одни координаты курсора в другие (хз зачем, но работает)
Vector3 mouseScreenToWorld = Camera.main.ScreenToWorldPoint(mousePosition);
//Выведем текущие координаты курсора на экран
TextX.text = "X: " + mouseScreenToWorld.x + " - Конец";
TextY.text = "Y: " + mouseScreenToWorld.y + " - Конец";
// Запускаем повтор движения курсора
GoMove = true;
//Уничтожаем объект ТрайлРендерер (спецэффекты), который следовал за курсором пользователя
Destroy(inst_MyGO1);
// СОздаём новый объект ТрайлРендерер (спецэффекты), который будет следовать за курсором повтора
inst_MyGO2 = Instantiate(MouseFollow, new Vector3(listX[0], listY[0], distanceFromCamera), Quaternion.identity) as GameObject;
}
}
void Start()
{
}
void Update()
{
// КАЖДЫЙ КАДР
if (GoMove)
{
// ПОВТОР ДВИЖЕНИЯ КУРСОРА ВКЛЮЧЁН, т.е. сейчас система сама повторяет траекторию движения курсора
// Увеличиваем счётчик
i++;
if (i < listX.Count)
{
// Текущий номер списка меньше, чем количество в списке координат
//Переместим объект ТрайлРендерер в следующую координату
inst_MyGO2.transform.position = new Vector3(listX[i], listY[i], distanceFromCamera);
}
else
{
//Все координаты пройдены, очистим списки координат и установим переменные в исходное положение
listX.Clear();
listY.Clear();
i = -1;
GoMove = false;
}
}
}
}