/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.cirqwizard.generation; import org.cirqwizard.fx.Context; import org.cirqwizard.generation.optimizer.Chain; import org.cirqwizard.generation.optimizer.ChainDetector; import org.cirqwizard.gerber.GerberPrimitive; import org.cirqwizard.layers.*; import org.cirqwizard.settings.ToolSettings; import org.cirqwizard.generation.toolpath.Toolpath; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; public class ToolpathGenerationService extends GenerationService { public ToolpathGenerationService(Context context, Board.LayerType layer) { super(context, layer); } @Override public List<Chain> generate() { ToolSettings currentTool = getContext().getCurrentMillingTool(); int diameter = currentTool.getDiameter(); final ToolpathGenerator generator = new ToolpathGenerator(); List<GerberPrimitive> elements = (List<GerberPrimitive>) getContext().getPanel().getCombinedElements(getLayer()); generator.init(getContext().getPanel().getSize().getWidth() + 1, getContext().getPanel().getSize().getHeight() + 1, diameter / 2, diameter, elements, cancelledProperty()); setCurrentStage("Generating tool paths..."); progressProperty().bind(generator.progressProperty()); List<Toolpath> toolpaths = generator.generate(); if (isCancelled()) return null; if (toolpaths == null || toolpaths.size() == 0) return null; toolpaths = new ToolpathMerger(toolpaths, getMergeTolerance()).merge(); if (currentTool.getAdditionalPasses() > 0) { setCurrentStage("Generating additional passes..."); if (!currentTool.isAdditionalPassesPadsOnly()) { for (int i = 0 ; i < currentTool.getAdditionalPasses(); i++) { int offset = diameter * (100 - currentTool.getAdditionalPassesOverlap()) / 100; generator.init(getContext().getPanel().getSize().getWidth() + 1, getContext().getPanel().getSize().getHeight() + 1, diameter / 2 + offset * (i + 1), diameter, elements, cancelledProperty()); List<Toolpath> additionalToolpaths = generator.generate(); if (additionalToolpaths == null || additionalToolpaths.size() == 0) continue; if (isCancelled()) return null; toolpaths.addAll(new ToolpathMerger(additionalToolpaths, getMergeTolerance()).merge()); } } else { progressProperty().unbind(); generatePadsOnlyAdditionalPasses(); } } return new ChainDetector(toolpaths).detect(); } private List<Toolpath> generatePadsOnlyAdditionalPasses() { ToolSettings currentTool = getContext().getCurrentMillingTool(); List<? extends LayerElement> elements = getContext().getPanel().getBoards().stream(). map(b -> b.getBoard().getLayer(Board.LayerType.TOP)). filter(l -> l != null). map(Layer::getElements). flatMap(Collection::stream).collect(Collectors.toList()); AdditionalToolpathGenerator additionalGenerator = new AdditionalToolpathGenerator(getContext().getPanel().getSize().getWidth() + 1, getContext().getPanel().getSize().getHeight() + 1, currentTool.getAdditionalPasses(), currentTool.getAdditionalPassesOverlap(), currentTool.getDiameter(), (List<GerberPrimitive>) elements); progressProperty().unbind(); progressProperty().bind(additionalGenerator.progressProperty()); return new ToolpathMerger(additionalGenerator.generate(), getMergeTolerance()).merge(); } private int getMergeTolerance() { return getContext().getCurrentMillingTool().getDiameter() / 4; } }