dollar/dollar/Gesture.cpp

193 lines
5.5 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/debug.hpp>
#include <dollar/Gesture.hpp>
#include <dollar/tools.hpp>
#include <etk/uri/uri.hpp>
#include <ejson/ejson.hpp>
#include <esvg/esvg.hpp>
#include <etk/stdTools.hpp>
static etk::Vector<etk::Vector<vec2>> loadPointsJson(const ejson::Document& _doc) {
// extract lines:
etk::Vector<etk::Vector<vec2>> out;
const ejson::Array listOfLines = _doc["data"].toArray();
if (listOfLines.exist() == false) {
DOLLAR_WARNING("Reference element has no element named 'data' " << _doc["data"]);
return out;
}
for (auto itLines : listOfLines) {
ejson::Array listOfpoint = itLines.toArray();
etk::Vector<vec2> line;
for (auto itPoints : listOfpoint) {
ejson::Array pointsArray = itPoints.toArray();
line.pushBack(vec2(pointsArray[0].toNumber().get(), pointsArray[1].toNumber().get()));
}
if (line.size() > 1) {
out.pushBack(etk::move(line));
}
}
return out;
}
etk::Vector<etk::Vector<vec2>> dollar::loadPoints(const etk::Uri& _fileName, etk::String* _label, etk::String* _type) {
ejson::Document doc;
doc.load(_fileName);
if (_label != null) {
*_label = doc["value"].toString().get();
}
if (_type != null) {
*_type = doc["type"].toString().get();
}
// extract lines:
etk::Vector<etk::Vector<vec2>> out;
ejson::Array listOfLines = doc["data"].toArray();
for (auto itLines : listOfLines) {
ejson::Array listOfpoint = itLines.toObject()["list"].toArray();
etk::Vector<vec2> line;
for (auto itPoints : listOfpoint) {
ejson::Array pointsArray = itPoints.toArray();
line.pushBack(vec2(pointsArray[0].toNumber().get(), pointsArray[1].toNumber().get()));
}
if (line.size() > 1) {
out.pushBack(etk::move(line));
}
}
return out;
}
dollar::Gesture::Gesture():
m_name(""),
m_subId(0),
m_aspectRatio(0.0f),
m_path(){
}
bool dollar::Gesture::load(const etk::Uri& _fileName) {
etk::String extention = etk::toLower(_fileName.getPath().getExtention());
if (extention == "json") {
return loadJSON(_fileName);
} else if (extention == "svg") {
return loadSVG(_fileName);
}
DOLLAR_ERROR("Un-sopported LOAD extention : " << _fileName);
DOLLAR_ERROR(" supported: [svg,json]");
return false;
}
bool dollar::Gesture::loadJSON(const etk::Uri& _fileName) {
ejson::Document doc;
doc.load(_fileName);
if (doc["type"].toString().get() != "REFERENCE") {
DOLLAR_WARNING("can not LOAD file that is not a reference");
}
m_name = doc["value"].toString().get();
m_subId = doc["sub-id"].toNumber().getU64(),
m_aspectRatio = doc["aspect-ratio"].toNumber().get(),
m_path = loadPointsJson(doc);
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
return true;
}
bool dollar::Gesture::loadSVG(const etk::Uri& _fileName) {
esvg::Document doc;
doc.load(_fileName);
etk::Vector<etk::String> plop = etk::split(_fileName.getPath().getFileName(), '_');
m_name = plop[0];
m_subId = etk::string_to_int32_t(plop[1]);
m_path = doc.getLines();
// SVG is written in the oposite mode ==> need to invert it ...
for (auto &it : m_path) {
for (auto &it2 : it) {
it2.setY(it2.y()*-1);
}
}
DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size());
return true;
}
bool dollar::Gesture::store(const etk::Uri& _fileName) {
etk::String extention = etk::toLower(_fileName.getPath().getExtention());
if (extention == "json") {
storeJSON(_fileName);
return true;
} else if (extention == "svg") {
storeSVG(_fileName);
return true;
}
DOLLAR_ERROR("Un-sopported STORE extention : " << _fileName);
DOLLAR_ERROR(" supported: [svg,json]");
return false;
}
void dollar::Gesture::storeJSON(const etk::Uri& _fileName) {
ejson::Document doc;
doc.add("type", ejson::String("REFERENCE"));
doc.add("value", ejson::String(m_name));
doc.add("sub-id", ejson::Number(m_subId));
doc.add("aspect-ratio", ejson::Number(m_aspectRatio));
ejson::Array data;
doc.add("data", data);
for (auto &it : m_path) {
ejson::Array path;
for (auto &pathIt : it) {
ejson::Array value;
value.add(ejson::Number(pathIt.x()));
value.add(ejson::Number(pathIt.y()));
path.add(value);
}
data.add(path);
}
doc.store(_fileName);
}
void dollar::Gesture::storeSVG(const etk::Uri& _fileName, bool _storeDot) {
etk::Vector<etk::Vector<vec2>> strokes = dollar::scaleToOne(m_path, true);
etk::String data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
data += "<svg height=\"100\" width=\"100\">\n";
for (auto &itLines : strokes) {
data += " <polyline fill=\"none\" stroke=\"black\" stroke-opacity=\"1\" stroke-width=\"2\"\n";
data += " points=\"";
bool first = true;
for (auto& itPoints : itLines) {
if (first == false) {
data += " ";
}
first = false;
data += etk::toString(itPoints.x()*100.0f) + "," + etk::toString((1.0-itPoints.y())*100.0f);
}
data += "\"\n";
data += " />\n";
}
if (_storeDot == true) {
/*
for (auto &it : m_enginePoints) {
data += " <circle fill=\"red\" cx=\"" + etk::toString(it.x()*100.0f) + "\" cy=\"" + etk::toString((1.0-it.y())*100.0f) + "\" r=\"0.6\"/>\n";
}
*/
}
data += "</svg>\n";
{
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(_fileName);
if (fileIO->open(etk::io::OpenMode::Write) == false) {
return;
}
fileIO->writeAll(data);
fileIO->close();
}
}
void dollar::Gesture::set(const etk::String& _name, uint32_t _subId, etk::Vector<etk::Vector<vec2>> _path) {
m_name = _name;
m_subId = _subId;
m_path = _path;
}