RectangleAperture.java
package com.varnernet.gerb4j;
import com.varnernet.gerb4j.render.GerberOutputTarget;
import java.awt.BasicStroke;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
* A rectangular aperture.
*
* <p>A rectangle aperture defines a rectangular shape that can be flashed or used for drawing lines.
* It may optionally have a hole in the center.
*/
public final class RectangleAperture extends Aperture {
private final double xSize;
private final double ySize;
private final double holeDiameter;
/**
* Creates a new rectangle aperture.
*
* @param id the aperture identifier
* @param xSize the width of the rectangle
* @param ySize the height of the rectangle
* @param holeDiameter the diameter of the optional hole (0.0 for no hole)
*/
public RectangleAperture(
final String id, final String xSize, final String ySize, final String holeDiameter) {
super(id);
this.xSize = Double.parseDouble(xSize);
this.ySize = Double.parseDouble(ySize);
this.holeDiameter = (holeDiameter == null) ? 0.0 : Double.parseDouble(holeDiameter);
}
/**
* Returns the width of the rectangle.
*
* @return the width
*/
public double getWidth() {
return xSize;
}
/**
* Returns the height of the rectangle.
*
* @return the height
*/
public double getHeight() {
return ySize;
}
/**
* Returns the diameter of the optional hole.
*
* @return the hole diameter (0.0 if no hole)
*/
public double getHoleDiameter() {
return holeDiameter;
}
/**
* Bounds centred at (0,0).
*/
@Override
public Rectangle2D getBounds() {
return new Rectangle2D.Double(-xSize / 2.0, -ySize / 2.0, xSize, ySize);
}
/**
* Stroke width for D01 linear draws. Per spec §4.8.4, a rectangle aperture sweeps its full
* cross-section along the path. We approximate this using min(xSize, ySize) as the stroke width.
*/
@Override
public double getStrokeWidth() {
return Math.min(xSize, ySize);
}
/**
* Rectangle apertures produce flat (butt) end caps.
*/
@Override
public int getCapStyle() {
return BasicStroke.CAP_BUTT;
}
/**
* Rectangle apertures use miter joins at shared vertices.
*/
@Override
public int getJoinStyle() {
return BasicStroke.JOIN_MITER;
}
/**
* Returns the rectangle cross-section for swept-region D01 rendering. Per Gerber spec §4.8.4, the
* cross-section of the drawn line is the full axis-aligned rectangle, not a reduced stroke width.
*/
@Override
public Shape getApertureShape() {
return new Rectangle2D.Double(-xSize / 2.0, -ySize / 2.0, xSize, ySize);
}
@Override
public void render(final Point2D flashPoint, final GerberOutputTarget target, final Polarity polarity) {
target.drawRectangle(flashPoint, xSize, ySize, 0.0, polarity);
if (holeDiameter > 0) {
target.drawCircle(flashPoint, holeDiameter, 0.0, invertPolarity(polarity));
}
}
}