/* 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.gerber; import javafx.scene.canvas.GraphicsContext; import org.cirqwizard.geom.Arc; import org.cirqwizard.geom.Point; import java.awt.*; import java.awt.geom.Arc2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class Region extends GerberPrimitive { private List<GerberPrimitive> segments = new ArrayList<>(); public Region(Polarity polarity) { super(polarity); } public void addSegment(GerberPrimitive segment) { segments.add(segment); } public List<GerberPrimitive> getSegments() { return segments; } @Override public void rotate(boolean clockwise) { for (GerberPrimitive segment : segments) segment.rotate(clockwise); } @Override public void move(Point point) { for (GerberPrimitive segment : segments) segment.move(point); } @Override public Point getMin() { int minX = segments.stream().mapToInt(p -> p.getMin().getX()).min().getAsInt(); int minY = segments.stream().mapToInt(p -> p.getMin().getY()).min().getAsInt(); return new Point(minX, minY); } @Override public Point getMax() { int maxX = segments.stream().mapToInt(p -> p.getMax().getX()).max().getAsInt(); int maxY = segments.stream().mapToInt(p -> p.getMax().getY()).max().getAsInt(); return new Point(maxX, maxY); } @Override public void render(Graphics2D g, double inflation) { Path2D polygon = new GeneralPath(); Point p = ((InterpolatingShape) getSegments().get(0)).getFrom(); polygon.moveTo(p.getX(), p.getY()); for (GerberPrimitive segment : getSegments()) { if (segment instanceof LinearShape) { LinearShape linearShape = (LinearShape) segment; polygon.lineTo(linearShape.getTo().getX(), linearShape.getTo().getY()); } else if (segment instanceof CircularShape) { Arc arc = ((CircularShape) segment).getArc(); polygon.append(new Arc2D.Double(arc.getCenter().getX() - arc.getRadius(), arc.getCenter().getY() - arc.getRadius(), arc.getRadius() * 2, arc.getRadius() * 2, -Math.toDegrees(arc.getStart()), Math.toDegrees(arc.getAngle()) * (arc.isClockwise() ? 1 : -1), Arc2D.OPEN), true); } } g.fill(polygon); float width = (float) inflation * 2; if (width < 0) { width *= -1; g.setColor(getPolarity() == GerberPrimitive.Polarity.DARK ? Color.BLACK : Color.WHITE); } g.setStroke(new BasicStroke(width, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER)); for (GerberPrimitive segment : getSegments()) { if (segment instanceof LinearShape) { LinearShape linearShape = (LinearShape) segment; g.draw(new Line2D.Double(linearShape.getFrom().getX(), linearShape.getFrom().getY(), linearShape.getTo().getX(), linearShape.getTo().getY())); } else if (segment instanceof CircularShape) { Arc arc = ((CircularShape) segment).getArc(); g.draw(new Arc2D.Double(arc.getCenter().getX() - arc.getRadius(), arc.getCenter().getY() - arc.getRadius(), arc.getRadius() * 2, arc.getRadius() * 2, -Math.toDegrees(arc.getStart()), Math.toDegrees(arc.getAngle()) * (arc.isClockwise() ? 1 : -1), Arc2D.OPEN)); } } } @Override public boolean isVisible() { return true; } @Override public void render(GraphicsContext g) { g.beginPath(); InterpolatingShape firstElement = (InterpolatingShape) getSegments().get(0); g.moveTo(firstElement.getFrom().getX(), firstElement.getFrom().getY()); for (GerberPrimitive segment : getSegments()) { if (segment instanceof LinearShape) g.lineTo(((LinearShape)segment).getTo().getX(), ((LinearShape)segment).getTo().getY()); else if (segment instanceof CircularShape) { Arc arc = ((CircularShape) segment).getArc(); g.arc(arc.getCenter().getX(), arc.getCenter().getY(), arc.getRadius(), arc.getRadius(), -Math.toDegrees(arc.getStart()), Math.toDegrees(arc.getAngle()) * (arc.isClockwise() ? 1 : -1)); } } g.closePath(); g.fill(); } @Override public Object clone() throws CloneNotSupportedException { Region clone = (Region)super.clone(); clone.segments = segments.stream().map(s -> { try { return (GerberPrimitive) s.clone(); } catch (CloneNotSupportedException e) {} return null; }).collect(Collectors.toList()); return clone; } }