Skip to content

Commit

Permalink
Add offset feature
Browse files Browse the repository at this point in the history
  • Loading branch information
eyal0 committed Jun 26, 2020
1 parent 6066fe1 commit a6fba12
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 31 deletions.
8 changes: 4 additions & 4 deletions board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ void Board::createLayers()
// Figure out how much margin the extra passes might make.
extra_passes_margin = tool_diameter + (tool_diameter - overlap_width) * extra_passes;
}
min_x = std::min(min_x, importer->get_min_x() - extra_passes_margin);
max_x = std::max(max_x, importer->get_max_x() + extra_passes_margin);
min_y = std::min(min_y, importer->get_min_y() - extra_passes_margin);
max_y = std::max(max_y, importer->get_max_y() + extra_passes_margin);
min_x = std::min(min_x, importer->get_min_x() - extra_passes_margin - trace_mill->offset);
max_x = std::max(max_x, importer->get_max_x() + extra_passes_margin + trace_mill->offset);
min_y = std::min(min_y, importer->get_min_y() - extra_passes_margin - trace_mill->offset);
max_y = std::max(max_y, importer->get_max_y() + extra_passes_margin + trace_mill->offset);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ void do_pcb2gcode(int argc, const char* argv[]) {
isolator->extra_passes = vm["extra-passes"].as<int>();
isolator->isolation_width = vm["isolation-width"].as<Length>().asInch(unit);
isolator->optimise = vm["optimise"].as<Length>().asInch(unit);
isolator->offset = vm["offset"].as<Length>().asInch(unit);
isolator->preserve_thermal_reliefs = vm["preserve-thermal-reliefs"].as<bool>();
isolator->eulerian_paths = vm["eulerian-paths"].as<bool>();
isolator->path_finding_limit = vm["path-finding-limit"].as<size_t>();
Expand Down Expand Up @@ -151,6 +152,7 @@ void do_pcb2gcode(int argc, const char* argv[]) {
cutter->zchange = vm["zchange"].as<Length>().asInch(unit);
cutter->stepsize = vm["cut-infeed"].as<Length>().asInch(unit);
cutter->optimise = vm["optimise"].as<Length>().asInch(unit);
cutter->offset = vm["offset"].as<Length>().asInch(unit);
cutter->eulerian_paths = vm["eulerian-paths"].as<bool>();
cutter->path_finding_limit = vm["path-finding-limit"].as<size_t>();
cutter->g0_vertical_speed = vm["g0-vertical-speed"].as<Velocity>().asInchPerMinute(unit);
Expand Down
1 change: 1 addition & 0 deletions mill.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class RoutingMill: public Mill {
double g0_horizontal_speed;
double backtrack;
double stepsize;
double offset; // Stay away from the traces by this amount.
};

/******************************************************************************/
Expand Down
16 changes: 6 additions & 10 deletions options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,11 @@ void fix_variables_map(po::variables_map& vm) {
vm.at("min-milldrill-hole-diameter").value() = Length(0);
}
// Deal with deprecated offset option.
if (vm.count("offset")) {
if (vm.at("mill-diameters").defaulted()) {
vm.at("mill-diameters").as<std::vector<CommaSeparated<Length>>>().clear();
vm.at("mill-diameters").as<std::vector<CommaSeparated<Length>>>().push_back({vm["offset"].as<Length>()*2.0});
} else {
throw pcb2gcode_parse_exception("Can't specify \"offset\" and \"mill-diameter\" together.", ERR_INVALIDPARAMETER);
}
if (vm.count("offset") && vm.at("mill-diameters").defaulted()) {
vm.at("mill-diameters").as<std::vector<CommaSeparated<Length>>>().clear();
vm.at("mill-diameters").as<std::vector<CommaSeparated<Length>>>().push_back({vm["offset"].as<Length>()*2.0});
vm.at("offset").value() = Length(0);
}
vm.erase("offset");

if (vm["bridgesnum"].as<unsigned int>() > 0 && vm["bridges"].as<Length>().asInch(1) <= 0) {
vm.at("bridgesnum").value() = (unsigned int) 0;
Expand Down Expand Up @@ -224,8 +220,8 @@ options::options()
("front", po::value<string>(),"front side RS274-X .gbr")
("back", po::value<string>(), "back side RS274-X .gbr")
("voronoi", po::value<bool>()->default_value(false)->implicit_value(true), "generate voronoi regions")
("offset", po::value<Length>(), "[DEPRECATED} use --mill-diameters and --milling-overlap."
" Distance between the PCB traces and the end mill path; usually half the isolation width")
("offset", po::value<Length>()->default_value(0), "Note: Prefer to use --mill-diameters and --milling-overlap if you just that's what you mean."
" An optional offset to add to all traces, useful if the bit has a little slop that you want to keep out of the trace.")
("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%")),
Expand Down
4 changes: 2 additions & 2 deletions options_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ BOOST_AUTO_TEST_CASE(available_drills) {
}

BOOST_AUTO_TEST_CASE(offset) {
BOOST_CHECK_EQUAL(get_count("pcb2gcode --offset 5mm", "offset"), 0);
BOOST_CHECK_EQUAL(get_count("pcb2gcode --offset 5mm", "offset"), 1);
BOOST_CHECK_EQUAL(get_value<Length>("pcb2gcode --offset 5mm", "offset"), Length(0));
BOOST_CHECK_EQUAL(get_value<std::vector<CommaSeparated<Length>>>("pcb2gcode --offset 5mm", "mill-diameters"),
std::vector<CommaSeparated<Length>>{{parse_unit<Length>("10mm")}});
BOOST_CHECK_THROW(parse("pcb2gcode --offset 5mm --mill-diameters 5mm"), pcb2gcode_parse_exception);
}

BOOST_AUTO_TEST_CASE(mill_diameters) {
Expand Down
27 changes: 13 additions & 14 deletions surface_vectorial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ vector<pair<linestring_type_fp, bool>> Surface_vectorial::get_single_toolpath(
const auto& current_voronoi = trace_index < voronoi.size() ? voronoi[trace_index] : thermal_holes[trace_index - voronoi.size()];
const vector<multi_polygon_type_fp> polygons =
offset_polygon(current_trace, current_voronoi,
diameter, overlap, extra_passes + 1, do_voronoi);
diameter, overlap, extra_passes + 1, do_voronoi, mill->offset);
multi_polygon_type_fp keep_in;
keep_in.push_back(current_voronoi);
optional<multi_polygon_type_fp> keep_out;
Expand Down Expand Up @@ -799,7 +799,7 @@ vector<pair<coordinate_type_fp, vector<shared_ptr<icoords>>>> Surface_vectorial:
if (trace_index < vectorial_surface->first.size()) {
// This doesn't run for thermal holes.
multi_polygon_type_fp temp;
bg_helpers::buffer(vectorial_surface->first.at(trace_index), temp, tool_diameter/2 - mill->tolerance);
bg_helpers::buffer(vectorial_surface->first.at(trace_index), temp, tool_diameter/2 + mill->offset - mill->tolerance);
already_milled_shrunk = already_milled_shrunk + temp;
}
}
Expand Down Expand Up @@ -906,32 +906,34 @@ void Surface_vectorial::add_mask(shared_ptr<Surface_vectorial> surface) {
// milling for thermal reliefs. The voronoi is the shape that
// encloses the input and outside which we have no need to mill
// because that will be handled by another call to this function. The
// diameter and overlap required of the tool are specified. Steps is
// diameter is the diameter of the tool and the overlap is by how much each pass should overlap the prevoius pass. Steps is
// how many passes to do, including the first pass. If do_voronoi is
// true then isolation should be done from the voronoi region inward
// instead of from the trace outward.
// instead of from the trace outward. The offset is how far to kee away from any trace, useful if the milling bit has some diameter that it is guaranteed to mill but also some slop that causes it to sometimes mill beyond its diameter.
vector<multi_polygon_type_fp> Surface_vectorial::offset_polygon(
const optional<polygon_type_fp>& input,
const polygon_type_fp& voronoi_polygon,
coordinate_type_fp diameter,
coordinate_type_fp overlap,
unsigned int steps, bool do_voronoi) const {
unsigned int steps, bool do_voronoi,
coordinate_type_fp offset) const {
// The polygons to add to the PNG debugging output files.
// Mask the polygon that we need to mill.
multi_polygon_type_fp masked_milling_poly;
masked_milling_poly.push_back(do_voronoi ? voronoi_polygon : *input); // Milling voronoi or trace?
if (!input) {
// This means that we are milling a thermal so we need to move inward
// slightly to accommodate the thickness of the millbit.
multi_polygon_type_fp temp;
bg_helpers::buffer(masked_milling_poly, temp, -diameter/2);
bg_helpers::buffer(masked_milling_poly, temp, -diameter/2 - offset);
masked_milling_poly = temp;
}
// This is the area that the milling must not cross so that it
// doesn't dig into the trace. We only need this if there is an
// input which is not the case if this is a thermal hole.
multi_polygon_type_fp path_minimum;
if (input) {
bg_helpers::buffer(*input, path_minimum, diameter/2);
bg_helpers::buffer(*input, path_minimum, diameter/2 + offset);
}

multi_polygon_type_fp masked_milling_polys;
Expand Down Expand Up @@ -979,14 +981,11 @@ vector<multi_polygon_type_fp> Surface_vectorial::offset_polygon(
}

multi_polygon_type_fp mpoly;
if (expand_by == 0) {
// We simply need to mill every ring in the shape.
mpoly = masked_milling_polys;
multi_polygon_type_fp mpoly_temp;
bg_helpers::buffer(masked_milling_polys, mpoly_temp, expand_by + offset);
if (expand_by + offset == 0) {
mpoly = mpoly_temp;
} else {
multi_polygon_type_fp mpoly_temp;
// Buffer should be done on floating point polygons.
bg_helpers::buffer(masked_milling_polys, mpoly_temp, expand_by);

if (!do_voronoi) {
mpoly = mpoly_temp & voronoi_polygon;
} else {
Expand Down
3 changes: 2 additions & 1 deletion surface_vectorial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ class Surface_vectorial: private boost::noncopyable {
const polygon_type_fp& voronoi,
coordinate_type_fp diameter,
coordinate_type_fp overlap,
unsigned int steps, bool do_voronoi) const;
unsigned int steps, bool do_voronoi,
coordinate_type_fp offset) const;
multi_linestring_type_fp post_process_toolpath(const std::shared_ptr<RoutingMill>& mill, const std::vector<std::pair<linestring_type_fp, bool>>& toolpath) const;
void write_svgs(const std::string& tool_suffix, coordinate_type_fp tool_diameter,
const std::vector<std::vector<std::pair<linestring_type_fp, bool>>>& new_trace_toolpaths,
Expand Down

0 comments on commit a6fba12

Please sign in to comment.