DrawingOperation.java
package com.varnernet.gerb4j.render;
import com.varnernet.gerb4j.ApertureTransform;
import com.varnernet.gerb4j.Mirror;
import com.varnernet.gerb4j.Polarity;
import com.varnernet.gerb4j.QuadrantMode;
import java.awt.geom.Point2D;
/**
* Represents a single drawing operation (D01, D02, D03). Captures the operation type, aperture,
* coordinates, and the graphics-state snapshot at the time of the operation.
*
* <p>All fields are immutable (final). The graphics-state snapshot (polarity, mirroring, rotation,
* scaling) is grouped into an {@link ApertureTransform}.
*/
public final class DrawingOperation implements GerberOperation {
/**
* The type of drawing operation corresponding to a Gerber D-code.
*/
public enum Type {
/**
* Move operation (D02).
*/
MOVE, // D02
/**
* Draw operation (D01).
*/
DRAW, // D01
/**
* Flash operation (D03).
*/
FLASH // D03
}
private final Type type;
private final String apertureId;
private final Point2D point;
/**
* For arc operations: the (I, J) center offset relative to the start point.
*/
private final Point2D interpolationPoint;
private final Polarity polarity;
private final ApertureTransform transform;
/**
* For arc DRAW operations: {@code true} = G02 (clockwise), {@code false} = G03.
*/
private final boolean clockwise;
/**
* For arc DRAW operations: quadrant mode active at parse time (G74 vs G75).
*/
private final QuadrantMode quadrantMode;
// ── Constructors ──────────────────────────────────────────────────────────
/**
* Convenience constructor for simple operations without graphics state.
*
* @param type the operation type
* @param apertureId the aperture ID
* @param point the point
*/
public DrawingOperation(final Type type, final String apertureId, final Point2D point) {
this(
type, apertureId, point, null, ApertureTransform.IDENTITY, null, false, QuadrantMode.MULTI);
}
/**
* Constructor with separate transform components (convenience for callers).
*
* @param type Operation type
* @param apertureId Aperture ID string
* @param point (X, Y) coordinate
* @param polarity Polarity snapshot at record time
* @param transform Aperture transform (mirroring, rotation, scaling)
* @param interpolationPoint (I, J) arc-centre offset, or null for linear ops
*/
public DrawingOperation(
final Type type,
final String apertureId,
final Point2D point,
final Polarity polarity,
final ApertureTransform transform,
final Point2D interpolationPoint) {
this(
type,
apertureId,
point,
polarity,
transform,
interpolationPoint,
false,
QuadrantMode.MULTI);
}
/**
* Constructor with separate transform components (convenience for callers).
*
* @param type Operation type
* @param apertureId Aperture ID string
* @param point (X, Y) coordinate
* @param polarity Polarity snapshot at record time
* @param mirroring Mirror snapshot (may be null → NONE)
* @param rotation Rotation snapshot in degrees (may be null → 0)
* @param scaling Scaling snapshot (may be null → 1.0)
* @param interpolationPoint (I, J) arc-centre offset, or null for linear ops
*/
public DrawingOperation(
final Type type,
final String apertureId,
final Point2D point,
final Polarity polarity,
final Mirror mirroring,
final Double rotation,
final Double scaling,
final Point2D interpolationPoint) {
this(
type,
apertureId,
point,
polarity,
new ApertureTransform(mirroring, rotation, scaling),
interpolationPoint,
false,
QuadrantMode.MULTI);
}
/**
* Full constructor used during parsing (with explicit clockwise flag and quadrant mode).
*
* @param type the operation type
* @param apertureId the aperture ID
* @param point the point
* @param polarity the polarity
* @param transform the aperture transform
* @param interpolationPoint the interpolation point
* @param clockwise the clockwise flag
* @param quadrantMode the quadrant mode
*/
public DrawingOperation(
final Type type,
final String apertureId,
final Point2D point,
final Polarity polarity,
final ApertureTransform transform,
final Point2D interpolationPoint,
final boolean clockwise,
final QuadrantMode quadrantMode) {
this.type = type;
this.apertureId = apertureId;
this.point = point != null ? new Point2D.Double(point.getX(), point.getY()) : null;
this.polarity = polarity;
this.transform = transform != null ? transform : ApertureTransform.IDENTITY;
this.interpolationPoint = interpolationPoint;
this.clockwise = clockwise;
this.quadrantMode = quadrantMode != null ? quadrantMode : QuadrantMode.MULTI;
}
// ── Accessors ─────────────────────────────────────────────────────────────
/**
* Returns the operation type.
*
* @return the type
*/
public Type getType() {
return type;
}
/**
* Returns the aperture ID.
*
* @return the aperture ID
*/
public String getApertureId() {
return apertureId;
}
/**
* Returns the point.
*
* @return the point
*/
public Point2D getPoint() {
return point;
}
/**
* Returns the interpolation point.
*
* @return the interpolation point
*/
public Point2D getInterpolationPoint() {
return interpolationPoint;
}
/**
* Returns the polarity.
*
* @return the polarity
*/
public Polarity getPolarity() {
return polarity;
}
/**
* Returns the full aperture-transform snapshot for this operation.
*
* @return the aperture transform
*/
public ApertureTransform getApertureTransform() {
return transform;
}
// ── Legacy accessors kept for compatibility ────────────────────────────────
/**
* Returns the mirroring.
*
* @return the mirroring
*/
public Mirror getMirroring() {
return transform.mirroring();
}
/**
* Returns the rotation.
*
* @return the rotation
*/
public Double getRotation() {
return transform.rotation();
}
/**
* Returns the scaling.
*
* @return the scaling
*/
public Double getScaling() {
return transform.scaling();
}
/**
* For arc DRAW operations: {@code true} = G02 clockwise, {@code false} = G03.
*
* @return true if clockwise
*/
public boolean isClockwise() {
return clockwise;
}
/**
* For arc DRAW operations: the quadrant mode in effect at parse time.
*
* @return the quadrant mode
*/
public QuadrantMode getQuadrantMode() {
return quadrantMode;
}
}