/* 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 javafx.scene.shape.StrokeLineCap; import org.cirqwizard.gerber.appertures.*; import org.cirqwizard.geom.Point; import org.cirqwizard.gerber.appertures.macro.*; import java.awt.*; import java.awt.geom.*; public class Flash extends GerberPrimitive { private Point point; public Flash(int x, int y, Aperture aperture, Polarity polarity) { super(polarity); point = new Point(x, y); this.aperture = aperture; } public Point getPoint() { return point; } public int getX() { return point.getX(); } public int getY() { return point.getY(); } @Override public void rotate(boolean clockwise) { if (clockwise) point = new Point(point.getY(), -point.getX()); else point = new Point(-point.getY(), point.getX()); aperture = aperture.rotate(clockwise); } @Override public void move(Point p) { point = point.add(p); } @Override public Point getMin() { return point.subtract(new Point(aperture.getWidth() / 2, aperture.getHeight() / 2)); } @Override public Point getMax() { return point.add(new Point(aperture.getWidth() / 2, aperture.getHeight() / 2)); } @Override public void render(Graphics2D g, double inflation) { if (getAperture() instanceof CircularAperture) { double d = Math.max(((CircularAperture)getAperture()).getDiameter() + inflation * 2, 0); double r = d / 2; g.fill(new Ellipse2D.Double(getX() - r, getY() - r, d, d)); } else if (getAperture() instanceof RectangularAperture) { RectangularAperture aperture = (RectangularAperture)getAperture(); double w = Math.max(aperture.getDimensions()[0] + inflation * 2, 0); double h = Math.max(aperture.getDimensions()[1] + inflation * 2, 0); g.fill(new Rectangle2D.Double(getX() - aperture.getDimensions()[0] / 2 - inflation, getY() - aperture.getDimensions()[1] / 2 - inflation, w, h)); } else if (getAperture() instanceof OctagonalAperture) { double edgeOffset = (Math.pow(2, 0.5) - 1) / 2 * (((OctagonalAperture)getAperture()).getDiameter() + inflation * 2); double centerOffset = 0.5 * (((OctagonalAperture)getAperture()).getDiameter() + inflation * 2); double flashX = getX(); double flashY = getY(); Path2D polygon = new GeneralPath(); polygon.moveTo(centerOffset + flashX, edgeOffset + flashY); polygon.lineTo(edgeOffset + flashX, centerOffset + flashY); polygon.lineTo(-edgeOffset + flashX, centerOffset + flashY); polygon.lineTo(-centerOffset + flashX, edgeOffset + flashY); polygon.lineTo(-centerOffset + flashX, -edgeOffset + flashY); polygon.lineTo(-edgeOffset + flashX, -centerOffset + flashY); polygon.lineTo(edgeOffset + flashX, -centerOffset + flashY); polygon.lineTo(centerOffset + flashX, -edgeOffset + flashY); g.fill(polygon); } else if (getAperture() instanceof OvalAperture) { OvalAperture aperture = (OvalAperture)getAperture(); double flashX = getX(); double flashY = getY(); double width = Math.max(aperture.getWidth() + inflation * 2, 0); double height = Math.max(aperture.getHeight() + inflation * 2, 0); double d = Math.min(width, height); double l = aperture.isHorizontal() ? width - height : height - width; double xOffset = aperture.isHorizontal() ? l / 2 : 0; double yOffset = aperture.isHorizontal() ? 0 : l / 2; double rectX = aperture.isHorizontal() ? flashX - l / 2 : flashX - width / 2; double rectY = aperture.isHorizontal() ? flashY - height / 2 : flashY - l / 2; double rectWidth = aperture.isHorizontal() ? l : width; double rectHeight = aperture.isHorizontal() ? height : l; g.fill(new Ellipse2D.Double(flashX - xOffset - d / 2, flashY + yOffset - d / 2, d, d)); g.fill(new Ellipse2D.Double(flashX + xOffset - d / 2, flashY - yOffset - d / 2, d, d)); g.fill(new Rectangle2D.Double(rectX, rectY, rectWidth, rectHeight)); } else if (getAperture() instanceof ApertureMacro) { ApertureMacro macro = (ApertureMacro) getAperture(); for (MacroPrimitive p : macro.getPrimitives()) { if (p instanceof MacroCenterLine) { MacroCenterLine centerLine = (MacroCenterLine) p; org.cirqwizard.geom.Point from = centerLine.getFrom().add(getPoint()); org.cirqwizard.geom.Point to = centerLine.getTo().add(getPoint()); g.setStroke(new BasicStroke(centerLine.getHeight(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); g.draw(new Line2D.Float(from.getX(), from.getY(), to.getX(), to.getY())); } else if (p instanceof MacroVectorLine) { MacroVectorLine vectorLine = (MacroVectorLine) p; org.cirqwizard.geom.Point from = vectorLine.getTranslatedStart().add(getPoint()); org.cirqwizard.geom.Point to = vectorLine.getTranslatedEnd().add(getPoint()); g.setStroke(new BasicStroke(vectorLine.getWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); g.draw(new Line2D.Float(from.getX(), from.getY(), to.getX(), to.getY())); } else if (p instanceof MacroCircle) { MacroCircle circle = (MacroCircle) p; double d = circle.getDiameter(); double r = d / 2; org.cirqwizard.geom.Point point = circle.getCenter().add(getPoint()); g.fill(new Ellipse2D.Double(point.getX() - r, point.getY() - r, d, d)); } else if (p instanceof MacroOutline) { MacroOutline outline = (MacroOutline) p; double x = getX(); double y = getY(); Path2D polygon = new GeneralPath(); org.cirqwizard.geom.Point point = outline.getTranslatedPoints().get(0); polygon.moveTo(point.getX() + x, point.getY() + y); for (int i = 1; i < outline.getTranslatedPoints().size(); i++) { point = outline.getTranslatedPoints().get(i); polygon.lineTo(point.getX() + x, point.getY() + y); } g.fill(polygon); } } } } @Override public void render(GraphicsContext g) { if (getAperture() instanceof CircularAperture) { double d = ((CircularAperture)getAperture()).getDiameter(); double r = d / 2; g.fillOval(getX() - r, getY() - r, d, d); } else if (getAperture() instanceof RectangularAperture) { RectangularAperture aperture = (RectangularAperture)getAperture(); g.fillRect(getX() - aperture.getDimensions()[0] / 2, getY() - aperture.getDimensions()[1] / 2, aperture.getDimensions()[0], aperture.getDimensions()[1]); } else if (getAperture() instanceof OctagonalAperture) { double edgeOffset = (Math.pow(2, 0.5) - 1) / 2 * ((OctagonalAperture)getAperture()).getDiameter(); double centerOffset = 0.5 * ((OctagonalAperture)getAperture()).getDiameter(); double x = getX(); double y = getY(); g.beginPath(); g.moveTo(centerOffset + x, edgeOffset + y); g.lineTo(edgeOffset + x, centerOffset + y); g.lineTo(-edgeOffset + x, centerOffset + y); g.lineTo(-centerOffset + x, edgeOffset + y); g.lineTo(-centerOffset + x, -edgeOffset + y); g.lineTo(-edgeOffset + x, -centerOffset + y); g.lineTo(edgeOffset + x, -centerOffset + y); g.lineTo(centerOffset + x, -edgeOffset + y); g.closePath(); g.fill(); } else if (getAperture() instanceof OvalAperture) { OvalAperture aperture = (OvalAperture)getAperture(); double flashX = getX(); double flashY = getY(); double width = aperture.getWidth(); double height = aperture.getHeight(); double d = Math.min(width, height); double l = aperture.isHorizontal() ? width - height : height - width; double xOffset = aperture.isHorizontal() ? l / 2 : 0; double yOffset = aperture.isHorizontal() ? 0 : l / 2; g.fillOval(flashX + xOffset - d / 2, flashY + yOffset - d / 2, d, d); g.fillOval(flashX - xOffset - d / 2, flashY - yOffset - d / 2, d, d); double rectX = aperture.isHorizontal() ? flashX - l / 2 : flashX - width / 2; double rectY = aperture.isHorizontal() ? flashY - height / 2 : flashY - l / 2; double rectWidth = aperture.isHorizontal() ? l : width; double rectHeight = aperture.isHorizontal() ? height : l; g.fillRect(rectX, rectY, rectWidth, rectHeight); } else if (getAperture() instanceof ApertureMacro) { ApertureMacro macro = (ApertureMacro) getAperture(); for (MacroPrimitive p : macro.getPrimitives()) { if (p instanceof MacroCenterLine) { MacroCenterLine centerLine = (MacroCenterLine) p; Point from = centerLine.getFrom().add(getPoint()); Point to = centerLine.getTo().add(getPoint()); g.setLineCap(StrokeLineCap.BUTT); g.setLineWidth(centerLine.getHeight()); g.strokeLine(from.getX(), from.getY(), to.getX(), to.getY()); } else if (p instanceof MacroVectorLine) { MacroVectorLine vectorLine = (MacroVectorLine) p; Point from = vectorLine.getTranslatedStart().add(getPoint()); Point to = vectorLine.getTranslatedEnd().add(getPoint()); g.setLineCap(StrokeLineCap.BUTT); g.setLineWidth(vectorLine.getWidth()); g.strokeLine(from.getX(), from.getY(), to.getX(), to.getY()); } else if (p instanceof MacroCircle) { MacroCircle circle = (MacroCircle) p; double d = circle.getDiameter(); double r = d / 2; Point point = circle.getCenter().add(getPoint()); g.fillOval(point.getX() - r, point.getY() - r, d, d); } else if (p instanceof MacroOutline) { MacroOutline outline = (MacroOutline) p; double x = getX(); double y = getY(); g.beginPath(); Point point = outline.getPoints().get(0); g.moveTo(point.getX() + x, point.getY() + y); for (int i = 1; i < outline.getTranslatedPoints().size(); i++) { point = outline.getPoints().get(i); g.lineTo(point.getX() + x, point.getY() + y); } g.closePath(); g.fill(); } } } } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }