Created
April 8, 2020 15:55
-
-
Save zoecarver/5b2b2abf633fd855c6fbad12621fa05e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.cpp | |
// vector | |
// | |
// Created by Zoe Carver on 4/7/20. | |
// | |
#include <iostream> | |
#include <fstream> | |
#include <vector> | |
#include <optional> | |
#include <cassert> | |
using namespace std; | |
enum class Action | |
{ | |
Move, | |
Line, | |
Path | |
}; | |
static std::optional<Action> | |
classify_action( char c ) | |
{ | |
switch (c) { | |
case 'm': | |
case 'M': | |
return {Action::Move}; | |
case 'l': | |
case 'L': | |
return {Action::Line}; | |
case 'c': | |
case 'C': | |
return {Action::Path}; | |
default: | |
return {}; | |
} | |
} | |
struct Command | |
{ | |
Action action; | |
double x1, y1, x2, y2, x, y; | |
Command( Action action, | |
double x = 0, double y = 0, | |
double x1 = 0, double y1 = 0, | |
double x2 = 0, double y2 = 0 ) | |
: action( action ), x( x ), y( y ), x1( x1 ), y1( y1 ), x2( x2 ), y2( y2 ) | |
{ } | |
Command( ) { } | |
}; | |
static std::vector<Command> | |
read_commands( std::string file_name ) | |
{ | |
ifstream infile; | |
infile.open( file_name ); | |
if ( !infile.is_open() ) | |
{ | |
std::cout << "ERROR: could not open file." << std::endl; | |
return {}; | |
} | |
vector<Command> commands; | |
char action_c, dummy; | |
double x, y; | |
while( infile >> action_c >> x >> dummy >> y ) | |
{ | |
auto action = classify_action( action_c ); | |
if ( !action ) | |
{ | |
std::cout << "ERROR: could not classify action '" << action_c << "'\n"; | |
break; | |
} | |
if ( action == Action::Path ) | |
{ | |
double x1, y1, x2, y2; | |
infile >> x1 >> dummy >> y1 >> x2 >> dummy >> y2; | |
commands.emplace_back( action.value( ), x2, y2, x, y, x1, y1 ); | |
continue; | |
} | |
commands.emplace_back( action.value( ), x, y ); | |
} | |
return commands; | |
} | |
using Range = std::pair<double, double>; | |
static std::string | |
format_line( Range x, Range y, double m, double b ) | |
{ | |
std::string fmt = "y = %fx + %f \\\\{ %f < x < %f \\\\} \\\\{ %f < y < %f \\\\}"; | |
size_t size = snprintf( nullptr, 0, fmt.c_str(), | |
m, b, x.first, x.second, y.first, y.second ) + 1; | |
std::unique_ptr<char[]> buff( new char[ size ] ); | |
snprintf( buff.get(), size, fmt.c_str(), | |
m, b, x.first, x.second, y.first, y.second ); | |
return std::string( buff.get(), buff.get() + size - 1 ); | |
} | |
static auto empty_move = Command(Action::Move, 0, 0); | |
static std::string | |
emit_line( Command line, Command move ) | |
{ | |
auto delta_x = move.x - line.x; | |
auto delta_y = move.y - line.y; | |
auto m = delta_x == 0 && delta_y == 0 ? 0 : delta_y / delta_x; | |
auto range_x = make_pair( min( move.x, line.x ), max( move.x, line.x ) ); | |
auto range_y = make_pair( min( move.y, line.y ), max( move.y, line.y ) ); | |
auto b = - ( ( m * line.x ) - line.y ); | |
return format_line( range_x, range_y, m, b ); | |
} | |
static std::string | |
format_line( Range p1, Range p2, Range p3, Range p4 ) | |
{ | |
std::string fmt = | |
"(" | |
"((1-t)^{3}%f + 3t(1-t)^{2}%f + 3t^{2}(1-t)%f + t^{3} %f)," | |
"((1-t)^{3}%f + 3t(1-t)^{2}%f + 3t^{2}(1-t)%f + t^{3} %f)" | |
")"; | |
size_t size = snprintf( nullptr, 0, fmt.c_str(), | |
p1.first, p2.first, p3.first, p4.first, | |
p1.second, p2.second, p3.second, p4.second ) + 1; | |
std::unique_ptr<char[]> buff( new char[ size ] ); | |
snprintf( buff.get(), size, fmt.c_str(), | |
p1.first, p2.first, p3.first, p4.first, | |
p1.second, p2.second, p3.second, p4.second ); | |
return std::string( buff.get(), buff.get() + size - 1 ); | |
} | |
static std::string | |
emit_path( Command path, Command move ) | |
{ | |
return format_line( make_pair(move.x, move.y), | |
make_pair(path.x1, path.y1), | |
make_pair(path.x2, path.y2), | |
make_pair(path.x, path.y) ); | |
} | |
static std::string | |
format_calc( std::string eq, int index ) | |
{ | |
std::string fmt = " calculator.setExpression({ id: 'graph%d', latex: '%s' });"; | |
size_t size = snprintf( nullptr, 0, fmt.c_str(), index, eq.c_str() ) + 1; | |
std::unique_ptr<char[]> buff( new char[ size ] ); | |
snprintf( buff.get(), size, fmt.c_str(), index, eq.c_str() ); | |
return std::string( buff.get(), buff.get() + size - 1 ); | |
} | |
int | |
main( int, const char * argv[] ) | |
{ | |
std::optional<Command> last; | |
std::vector<Command> commands = read_commands( argv[1] ); | |
std::vector<std::string> eqs; | |
for ( Command c : commands ) | |
{ | |
if ( c.action == Action::Move ) | |
{ | |
last = c; | |
continue; | |
} | |
if ( c.action == Action::Line ) | |
{ | |
eqs.push_back( emit_line( c, last ? last.value() : empty_move ) ); | |
last = c; | |
} | |
if ( c.action == Action::Path ) | |
{ | |
eqs.push_back( emit_path( c, last ? last.value() : empty_move ) ); | |
last = c; | |
} | |
} | |
int index = 0; | |
for ( auto &s : eqs ) | |
std::cout << format_calc(s, index++) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment