Skip to content

Commit

Permalink
Add milling-overlap option
Browse files Browse the repository at this point in the history
  • Loading branch information
eyal0 committed Jan 16, 2019
1 parent d73bde5 commit 5af6137
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 7 deletions.
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -42,6 +42,7 @@ BOOST_GEOMETRY
BOOST_STRING_ALGO
BOOST_FORMAT
BOOST_OPTIONAL
BOOST_VARIANT

PKG_CHECK_MODULES([glibmm], [glibmm-2.4 >= 2.8])
PKG_CHECK_MODULES([gdkmm], [gdkmm-2.4 >= 2.8])
Expand Down
4 changes: 3 additions & 1 deletion main.cpp
Expand Up @@ -96,7 +96,9 @@ void do_pcb2gcode(int argc, const char* argv[]) {
{
isolator = shared_ptr<Isolator>(new Isolator());
// TODO: support more than one mill-diameter.
isolator->tool_diameter = flatten(vm["mill-diameters"].as<std::vector<CommaSeparated<Length>>>())[0].asInch(unit);
Length tool_diameter = flatten(vm["mill-diameters"].as<std::vector<CommaSeparated<Length>>>())[0];
isolator->tool_diameter = tool_diameter.asInch(unit);
isolator->overlap_width = boost::apply_visitor(percent_visitor(tool_diameter), vm["milling-overlap"].as<boost::variant<Length, Percent>>()).asInch(unit);
isolator->voronoi = vm["voronoi"].as<bool>();
isolator->zwork = vm["zwork"].as<Length>().asInch(unit);
isolator->zsafe = vm["zsafe"].as<Length>().asInch(unit);
Expand Down
12 changes: 6 additions & 6 deletions mill.hpp
Expand Up @@ -55,12 +55,12 @@ class Mill
/*
*/
/******************************************************************************/
class RoutingMill: public Mill
{
public:
double tool_diameter;
bool optimise;
bool eulerian_paths;
class RoutingMill: public Mill {
public:
double tool_diameter;
bool optimise;
bool eulerian_paths;
double overlap_width; // How much to overlap the extra passes.
};

/******************************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions options.cpp
Expand Up @@ -27,6 +27,7 @@
#include <list>
#include <boost/exception/all.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/variant.hpp>
#include "units.hpp"
#include "available_drills.hpp"

Expand Down Expand Up @@ -202,6 +203,8 @@ options::options()
" Distance between the PCB traces and the end mill path; usually half the isolation width")
("mill-diameters", po::value<std::vector<CommaSeparated<Length>>>()->default_value({{Length(0)}})
->multitoken(), "Diameters of mill bits, used in the order that they are provided.")
("milling-overlap", po::value<boost::variant<Length, Percent>>()->default_value(parse_unit<Percent>("50%")),
"How much to overlap milling passes, from 0% to 100%")
("voronoi", po::value<bool>()->default_value(false)->implicit_value(true), "generate voronoi regions (requires --vectorial)")
("preserve-thermal-reliefs", po::value<bool>()->default_value(true)->implicit_value(true), "generate mill paths for thermal reliefs in voronoi mode")
("pre-milling-gcode", po::value<std::vector<string>>()->default_value(std::vector<string>{}, ""), "custom gcode inserted before the start of milling each trace (used to activate pump or fan or laser connected to fan)")
Expand Down
15 changes: 15 additions & 0 deletions options_tests.cpp
Expand Up @@ -76,4 +76,19 @@ BOOST_AUTO_TEST_CASE(mill_diameters) {
}));
}

BOOST_AUTO_TEST_CASE(milling_overlap) {
BOOST_CHECK_EQUAL(
(get_value<boost::variant<Length, Percent>>("pcb2gcode", "milling-overlap")),
(boost::variant<Length, Percent>(parse_unit<Percent>("50%"))));
BOOST_CHECK_EQUAL(
(get_value<boost::variant<Length, Percent>>("pcb2gcode --milling-overlap 10%", "milling-overlap")),
(boost::variant<Length, Percent>(parse_unit<Percent>("10%"))));
BOOST_CHECK_EQUAL(
(get_value<boost::variant<Length, Percent>>("pcb2gcode --milling-overlap 1mm", "milling-overlap")),
(boost::variant<Length, Percent>(parse_unit<Length>("1mm"))));
BOOST_CHECK_THROW(
(parse("pcb2gcode --milling-overlap 1rpm")),
pcb2gcode_parse_exception);
}

BOOST_AUTO_TEST_SUITE_END()
67 changes: 67 additions & 0 deletions units.hpp
Expand Up @@ -13,6 +13,7 @@
#include <boost/units/base_units/imperial/thou.hpp>
#include <boost/units/io.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/variant.hpp>

#include "common.hpp"

Expand Down Expand Up @@ -74,6 +75,13 @@ class Lexer {
throw units_parse_exception("division", input.substr(pos));
}
}
void get_percent() {
get_whitespace();
if (!get_exact("%")) {
throw units_parse_exception("percent", input.substr(pos));
}
}

bool at_end() {
return pos == input.size();
}
Expand Down Expand Up @@ -199,12 +207,25 @@ struct rpm_base_unit :
typedef rpm_base_unit::unit_type rpm_unit;
const boost::units::quantity<rpm_unit> rpm(1*rpm_base_unit::unit_type());

struct percent_base_dimension :
boost::units::base_dimension<percent_base_dimension, 3> {};
typedef percent_base_dimension::dimension_type percent_type;

struct percent_base_unit :
boost::units::base_unit<percent_base_unit, percent_type, 3> {
static std::string name() {return "percent";}
static std::string symbol() {return "%";}
};
typedef percent_base_unit::unit_type percent_unit;
const boost::units::quantity<percent_unit> percent(1*percent_base_unit::unit_type());

// shortcuts for Units defined below.
typedef Unit<boost::units::si::length> Length;
typedef Unit<boost::units::si::time> Time;
typedef Unit<revolution_unit> Revolution;
typedef Unit<boost::units::si::velocity> Velocity;
typedef Unit<rpm_unit> Rpm;
typedef Unit<percent_unit> Percent;

template<>
class Unit<boost::units::si::length> : public UnitBase<boost::units::si::length> {
Expand Down Expand Up @@ -351,6 +372,38 @@ class Unit<rpm_unit> : public UnitBase<rpm_unit> {
}
};

template<>
class Unit<percent_unit> : public UnitBase<percent_unit> {
public:
Unit(double value = 0, boost::optional<quantity> one = boost::none) : UnitBase(value, one) {}
using UnitBase::as;
double asPercent(double factor) const {
return as(factor, 1.0 * percent);
}
double asFraction(double factor) const {
return as(factor, 100.0 * percent);
}
static quantity get_unit(Lexer& lex) {
lex.get_percent();
return 1.0*percent;
}
};

class percent_visitor : public boost::static_visitor<Length> {
public:
percent_visitor(const Length& base) : base(base) {}
Length operator()(const Percent& p) const {
Length ret = base;
ret = ret * p.asFraction(1);
return ret;
}
Length operator()(const Length& l) const {
return base;
}
private:
Length base;
};

template <typename unit_t>
unit_t parse_unit(const std::string& s) {
Lexer lex(s);
Expand Down Expand Up @@ -379,6 +432,20 @@ inline std::istream& operator>>(std::istream& in, Unit<dimension_t>& unit) {
return in;
}

// Support variants as units.
template <typename dimension1_t, typename dimension2_t>
inline std::istream& operator>>(std::istream& in, boost::variant<Unit<dimension1_t>, Unit<dimension2_t>>& unit) {
std::vector<boost::program_options::invalid_option_value> exceptions;
std::string s(std::istreambuf_iterator<char>(in), {});
try {
unit = parse_unit<Unit<dimension1_t>>(s);
return in;
} catch (boost::program_options::invalid_option_value e) { }
Unit<dimension1_t> unit2;
unit = parse_unit<Unit<dimension2_t>>(s);
return in;
}

// Represents a few of the base unit, which can be input or output as a
// comma-separated list.
template <typename base_unit>
Expand Down

0 comments on commit 5af6137

Please sign in to comment.