Commit d89543cd authored by kraus's avatar kraus
Browse files

enable math expressions instead of simple numbers

parent 7b9d085a
......@@ -17,11 +17,13 @@ set (_SRCS
LogicalError.cpp
Mesher.cpp
MSLang.cpp
MSLang/ArgumentExtractor.cpp
MSLang/BoundingBox.cpp
MSLang/Difference.cpp
MSLang/Ellipse.cpp
MSLang/Intersection.cpp
MSLang/Mask.cpp
MSLang/matheval.cpp
MSLang/Polygon.cpp
MSLang/QuadTree.cpp
MSLang/Rectangle.cpp
......@@ -69,12 +71,15 @@ set (HDRS
LogicalError.h
Mesher.h
MSLang.h
MSLang/ArgumentExtractor.h
MSLang/AffineTransformation.h
MSLang/BoundingBox.h
MSLang/Difference.h
MSLang/Ellipse.h
MSLang/Intersection.h
MSLang/Mask.h
MSLang/matheval.h
MSLang/matheval.hpp
MSLang/Polygon.h
MSLang/QuadTree.h
MSLang/Rectangle.h
......
#include "Utilities/MSLang/ArgumentExtractor.h"
#include <stdexcept>
namespace mslang {
ArgumentExtractor::ArgumentExtractor(const std::string &input):
inputArguments_m(input)
{
const unsigned int length = input.length();
unsigned int pos = 0;
unsigned short level = 1;
unsigned int start = 0;
for (; pos < length; ++ pos) {
if (input[pos] == ')') {
-- level;
if (level == 0) {
argumentBoundaries_m.push_back(std::make_pair(start, pos - start));
break;
}
}
else if (input[pos] == '(')
++ level;
else if ((input[pos] == ','
|| input[pos] == ';')
&& level == 1) {
argumentBoundaries_m.push_back(std::make_pair(start, pos - start));
start = pos + 1;
}
}
inputArguments_m = inputArguments_m.substr(0, pos);
lengthConsumed_m = pos;
}
std::string ArgumentExtractor::get(unsigned int i) const {
if (i >= argumentBoundaries_m.size())
throw std::out_of_range("function only has " + std::to_string(argumentBoundaries_m.size()) + " arguments");
auto boundaries = argumentBoundaries_m[i];
return inputArguments_m.substr(boundaries.first, boundaries.second);
}
unsigned int ArgumentExtractor::getLengthConsumed() const {
return lengthConsumed_m;
}
unsigned int ArgumentExtractor::getNumArguments() const {
return argumentBoundaries_m.size();
}
}
\ No newline at end of file
#ifndef MSLANG_ARGUMENTEXTRACTOR_H
#define MSLANG_ARGUMENTEXTRACTOR_H
#include <string>
#include <vector>
#include <utility>
namespace mslang {
struct ArgumentExtractor {
ArgumentExtractor(const std::string &input);
std::string get(unsigned int i) const;
unsigned int getLengthConsumed() const;
unsigned int getNumArguments() const;
std::vector<std::pair<unsigned int, unsigned int>> argumentBoundaries_m;
std::string inputArguments_m;
unsigned int lengthConsumed_m;
};
}
#endif
\ No newline at end of file
#include "Utilities/MSLang/Ellipse.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include "Physics/Physics.h"
#include <boost/regex.hpp>
......@@ -115,19 +117,35 @@ namespace mslang {
}
bool Ellipse::parse_detail(iterator &it, const iterator &end, Function* fun) {
std::string str(it, end);
boost::regex argumentList(UDouble + "," + UDouble + "(\\).*)");
boost::smatch what;
if (!boost::regex_match(str, what, argumentList)) return false;
ArgumentExtractor arguments(std::string(it, end));
double width, height;
try {
width = parseMathExpression(arguments.get(0));
height = parseMathExpression(arguments.get(1));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
Ellipse *elps = static_cast<Ellipse*>(fun);
elps->width_m = atof(std::string(what[1]).c_str());
elps->height_m = atof(std::string(what[3]).c_str());
elps->width_m = width;
elps->height_m = height;
if (elps->width_m < 0.0) {
std::cout << "Ellipse: a negative width provided '"
<< arguments.get(0) << " = " << elps->width_m << "'"
<< std::endl;
return false;
}
if (elps->height_m < 0.0) {
std::cout << "Ellipse: a negative height provided '"
<< arguments.get(1) << " = " << elps->height_m << "'"
<< std::endl;
return false;
}
std::string fullMatch = what[0];
std::string rest = what[5];
it += (fullMatch.size() - rest.size() + 1);
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Mask.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include "Utilities/PortableBitmapReader.h"
#include <boost/regex.hpp>
......@@ -8,12 +10,9 @@ namespace mslang {
bool Mask::parse_detail(iterator &it, const iterator &end, Function* &fun) {
Mask *pixmap = static_cast<Mask*>(fun);
std::string str(it, end);
boost::regex argument("'([^,]+)'," + UDouble + "," + UDouble + "(\\).*)");
boost::smatch what;
if (!boost::regex_match(str, what, argument)) return false;
ArgumentExtractor arguments(std::string(it, end));
std::string filename = arguments.get(0);
std::string filename = what[1];
if (!boost::filesystem::exists(filename)) {
ERRORMSG("file '" << filename << "' doesn't exists" << endl);
return false;
......@@ -22,8 +21,30 @@ namespace mslang {
PortableBitmapReader reader(filename);
unsigned int width = reader.getWidth();
unsigned int height = reader.getHeight();
double pixel_width = atof(std::string(what[2]).c_str()) / width;
double pixel_height = atof(std::string(what[4]).c_str()) / height;
double pixel_width;
double pixel_height;
try {
pixel_width = parseMathExpression(arguments.get(1)) / width;
pixel_height = parseMathExpression(arguments.get(2)) / height;
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
if (pixel_width < 0.0) {
std::cout << "Mask: a negative width provided '"
<< arguments.get(0) << " = " << pixel_width * width << "'"
<< std::endl;
return false;
}
if (pixel_height < 0.0) {
std::cout << "Mask: a negative height provided '"
<< arguments.get(1) << " = " << pixel_height * height << "'"
<< std::endl;
return false;
}
for (unsigned int i = 0; i < height; ++ i) {
for (unsigned int j = 0; j < width; ++ j) {
......@@ -40,9 +61,7 @@ namespace mslang {
}
}
std::string fullMatch = what[0];
std::string rest = what[6];
it += (fullMatch.size() - rest.size() + 1);
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Polygon.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include "Utilities/Mesher.h"
#include "Physics/Physics.h"
......@@ -13,42 +15,25 @@ namespace mslang {
bool Polygon::parse_detail(iterator &it, const iterator &end, Function* &fun) {
Polygon *poly = static_cast<Polygon*>(fun);
ArgumentExtractor arguments(std::string(it, end));
std::vector<Vector_t> nodes;
std::string str(it, end);
boost::regex argument(Double + "," + Double + ";(.*)");
boost::regex argumentEnd(Double + "," + Double + "(\\).*)");
boost::smatch what;
while (boost::regex_match(str, what, argument)) {
Vector_t p(atof(std::string(what[1]).c_str()),
atof(std::string(what[3]).c_str()),
1.0);
nodes.push_back(p);
std::string fullMatch = what[0];
std::string rest = what[5];
it += (fullMatch.size() - rest.size());
str = std::string(it, end);
}
if (!boost::regex_match(str, what, argumentEnd) ||
nodes.size() < 2) return false;
Vector_t p(atof(std::string(what[1]).c_str()),
atof(std::string(what[3]).c_str()),
1.0);
nodes.push_back(p);
for (unsigned int i = 0; i + 1 < arguments.getNumArguments(); i += 2) {
try {
double x = parseMathExpression(arguments.get(i));
double y = parseMathExpression(arguments.get(i + 1));
nodes.push_back(Vector_t(x, y, 1.0));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
}
std::string fullMatch = what[0];
std::string rest = what[5];
it += (fullMatch.size() - rest.size() + 1);
str = std::string(it, end);
if (nodes.size() < 3) return false;
poly->triangulize(nodes);
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Rectangle.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include "Physics/Physics.h"
#include <boost/regex.hpp>
......@@ -107,15 +109,30 @@ namespace mslang {
boost::regex argumentList(UDouble + "," + UDouble + "(\\).*)");
boost::smatch what;
if (!boost::regex_match(str, what, argumentList)) return false;
Rectangle *rect = static_cast<Rectangle*>(fun);
rect->width_m = atof(std::string(what[1]).c_str());
rect->height_m = atof(std::string(what[3]).c_str());
ArgumentExtractor arguments(str);
try {
rect->width_m = parseMathExpression(arguments.get(0));
rect->height_m = parseMathExpression(arguments.get(1));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
if (rect->width_m < 0.0) {
std::cout << "Rectangle: a negative width provided '"
<< arguments.get(0) << " = " << rect->width_m << "'"
<< std::endl;
return false;
}
if (rect->height_m < 0.0) {
std::cout << "Rectangle: a negative height provided '"
<< arguments.get(1) << " = " << rect->height_m << "'"
<< std::endl;
return false;
}
std::string fullMatch = what[0];
std::string rest = what[5];
it += (fullMatch.size() - rest.size() + 1);
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Repeat.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include <boost/regex.hpp>
......@@ -37,39 +39,36 @@ namespace mslang {
Repeat *rep = static_cast<Repeat*>(fun);
if (!parse(it, end, rep->func_m)) return false;
boost::regex argumentListTrans("," + UInt + "," + Double + "," + Double + "\\)(.*)");
boost::regex argumentListRot("," + UInt + "," + Double + "\\)(.*)");
boost::smatch what;
std::string str(it, end);
if (boost::regex_match(str, what, argumentListTrans)) {
rep->N_m = atof(std::string(what[1]).c_str());
rep->shiftx_m = atof(std::string(what[2]).c_str());
rep->shifty_m = atof(std::string(what[4]).c_str());
rep->rot_m = 0.0;
std::string fullMatch = what[0];
std::string rest = what[6];
it += (fullMatch.size() - rest.size());
return true;
ArgumentExtractor arguments(std::string(++ it, end));
try {
if (arguments.getNumArguments() == 3) {
rep->N_m = parseMathExpression(arguments.get(0));
rep->shiftx_m = parseMathExpression(arguments.get(1));
rep->shifty_m = parseMathExpression(arguments.get(2));
rep->rot_m = 0.0;
} else if (arguments.getNumArguments() == 2) {
rep->N_m = parseMathExpression(arguments.get(0));
rep->shiftx_m = 0.0;
rep->shifty_m = 0.0;
rep->rot_m = parseMathExpression(arguments.get(1));
} else {
std::cout << "Repeat: number of arguments not supported" << std::endl;
return false;
}
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
if (boost::regex_match(str, what, argumentListRot)) {
rep->N_m = atof(std::string(what[1]).c_str());
rep->shiftx_m = 0.0;
rep->shifty_m = 0.0;
rep->rot_m = atof(std::string(what[2]).c_str());
std::string fullMatch = what[0];
std::string rest = what[4];
it += (fullMatch.size() - rest.size());
return true;
if (rep->N_m < 0) {
std::cout << "Repeat: a negative number of repetitions '"
<< arguments.get(0) << " = " << rep->N_m << "'"
<< std::endl;
}
return false;
it += (arguments.getLengthConsumed() + 1);
return true;
}
}
\ No newline at end of file
#include "Utilities/MSLang/Rotation.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include <boost/regex.hpp>
......@@ -37,18 +39,15 @@ namespace mslang {
Rotation *rot = static_cast<Rotation*>(fun);
if (!parse(it, end, rot->func_m)) return false;
boost::regex argumentList("," + Double + "\\)(.*)");
boost::smatch what;
std::string str(it, end);
if (!boost::regex_match(str, what, argumentList)) return false;
rot->angle_m = atof(std::string(what[1]).c_str());
std::string fullMatch = what[0];
std::string rest = what[3];
ArgumentExtractor arguments(std::string(++ it, end));
try {
rot->angle_m = parseMathExpression(arguments.get(0));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
it += (fullMatch.size() - rest.size());
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Shear.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include <boost/regex.hpp>
......@@ -41,22 +43,16 @@ namespace mslang {
Shear *shr = static_cast<Shear*>(fun);
if (!parse(it, end, shr->func_m)) return false;
boost::regex argumentList("," + Double + "," + Double + "\\)(.*)");
boost::smatch what;
std::string str(it, end);
if (!boost::regex_match(str, what, argumentList)) return false;
shr->angleX_m = atof(std::string(what[1]).c_str());
shr->angleY_m = atof(std::string(what[3]).c_str());
if (std::abs(shr->angleX_m) > 0.0 && std::abs(shr->angleY_m) > 0.0)
ArgumentExtractor arguments(std::string(++ it, end));
try {
shr->angleX_m = parseMathExpression(arguments.get(0));
shr->angleY_m = parseMathExpression(arguments.get(1));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
std::string fullMatch = what[0];
std::string rest = what[5];
it += (fullMatch.size() - rest.size());
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/Translation.h"
#include "Utilities/MSLang/ArgumentExtractor.h"
#include "Utilities/MSLang/matheval.h"
#include "Physics/Physics.h"
#include <boost/regex.hpp>
......@@ -38,19 +40,16 @@ namespace mslang {
Translation *trans = static_cast<Translation*>(fun);
if (!parse(it, end, trans->func_m)) return false;
boost::regex argumentList("," + Double + "," + Double + "\\)(.*)");
boost::smatch what;
std::string str(it, end);
if (!boost::regex_match(str, what, argumentList)) return false;
trans->shiftx_m = atof(std::string(what[1]).c_str());
trans->shifty_m = atof(std::string(what[3]).c_str());
std::string fullMatch = what[0];
std::string rest = what[5];
ArgumentExtractor arguments(std::string(++ it, end));
try {
trans->shiftx_m = parseMathExpression(arguments.get(0));
trans->shifty_m = parseMathExpression(arguments.get(1));
} catch (std::runtime_error &e) {
std::cout << e.what() << std::endl;
return false;
}
it += (fullMatch.size() - rest.size());
it += (arguments.getLengthConsumed() + 1);
return true;
}
......
#include "Utilities/MSLang/matheval.hpp"
namespace mslang {
double parseMathExpression(const std::string &str) {
return matheval::parse<double>(str, {});
}
}
\ No newline at end of file
#ifndef MSLANG_MATHEVAL_H
#define MSLANG_MATHEVAL_H
#include <string>
namespace mslang {
double parseMathExpression(const std::string &str);
}
#endif
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment