ObroundAperture.java
package com.varnernet.gerb4j;
import com.varnernet.gerb4j.render.GerberOutputTarget;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
/**
* An obround (stadium-shaped) aperture.
*
* <p>An obround is a rectangle with semicircular ends. The diameter of the semicircles equals
* the shorter dimension of the rectangle.
*/
public class ObroundAperture extends Aperture {
private final double xSize;
private final double ySize;
private final double holeDiameter;
/**
* Creates a new obround aperture.
*
* @param id the aperture identifier
* @param xSize the width of the obround
* @param ySize the height of the obround
* @param holeDiameter the diameter of the optional hole (0.0 for no hole)
*/
public ObroundAperture(
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 obround.
*
* @return the width
*/
public double getWidth() {
return xSize;
}
/**
* Returns the height of the obround.
*
* @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) — the enclosing rectangle of the stadium shape.
*/
@Override
public Rectangle2D getBounds() {
return new Rectangle2D.Double(-xSize / 2.0, -ySize / 2.0, xSize, ySize);
}
/**
* Stroke width for D01 linear draws. An obround (stadium) cross-section has semicircular ends
* whose diameter equals the short axis: min(xSize, ySize).
*/
@Override
public double getStrokeWidth() {
return Math.min(xSize, ySize);
}
/**
* Returns the obround (stadium) cross-section for swept-region D01 rendering. Per Gerber spec
* §4.8.4, the cross-section of the drawn line is the full stadium shape (rounded rectangle with
* semicircular ends).
*/
@Override
public Shape getApertureShape() {
double cornerDiam = Math.min(xSize, ySize);
return new RoundRectangle2D.Double(
-xSize / 2.0, -ySize / 2.0, xSize, ySize, cornerDiam, cornerDiam);
}
@Override
public void render(final Point2D flashPoint, final GerberOutputTarget target, final Polarity polarity) {
target.drawObround(flashPoint, xSize, ySize, 0.0, polarity);
if (holeDiameter > 0) {
target.drawCircle(flashPoint, holeDiameter, 0.0, invertPolarity(polarity));
}
}
}