张世豪
2025-12-05 2144172c7b961d4112850692ed77b46f1ae5d373
src/gecaoji/Gecaoji.java
@@ -12,6 +12,7 @@
/** Mower rendering helper. */
public class Gecaoji {
    private static final double ICON_PIXEL_SIZE = 48.0;
    private static final double ICON_SCALE_FACTOR = 0.8;
    private static final double MIN_SCALE = 1e-6;
    private static final Color FALLBACK_FILL = new Color(0, 150, 0);
@@ -19,6 +20,7 @@
    private final Ellipse2D.Double fallbackShape = new Ellipse2D.Double();
    private Point2D.Double position = new Point2D.Double();
    private boolean positionValid;
    private double headingDegrees;
    public Gecaoji() {
        mowerIcon = loadIcon();
@@ -27,7 +29,7 @@
    private Image loadIcon() {
        try {
            ImageIcon icon = new ImageIcon("image/mow.png");
            ImageIcon icon = new ImageIcon("image/gecaoji.png");
            if (icon.getIconWidth() <= 0 || icon.getIconHeight() <= 0) {
                return null;
            }
@@ -47,6 +49,7 @@
        double x = parseCoordinate(device.getRealtimeX());
        double y = parseCoordinate(device.getRealtimeY());
        double heading = parseHeading(device.getHeading());
        if (Double.isNaN(x) || Double.isNaN(y)) {
            positionValid = false;
            return;
@@ -56,6 +59,7 @@
        position.x = x;
        position.y = y;
        positionValid = true;
        headingDegrees = heading;
    }
    private void ensurePosition() {
@@ -79,12 +83,32 @@
        }
    }
    private double parseHeading(String value) {
        if (value == null) {
            return 0.0;
        }
        String trimmed = value.trim();
        if (trimmed.isEmpty() || "-1".equals(trimmed)) {
            return 0.0;
        }
        try {
            double parsed = Double.parseDouble(trimmed);
            if (!Double.isFinite(parsed)) {
                return 0.0;
            }
            double normalized = parsed % 360.0;
            return normalized < 0 ? normalized + 360.0 : normalized;
        } catch (NumberFormatException ex) {
            return 0.0;
        }
    }
    public void draw(Graphics2D g2d, double scale) {
        if (!positionValid) {
            return;
        }
        double worldSize = ICON_PIXEL_SIZE / Math.max(scale, MIN_SCALE);
    double worldSize = (ICON_PIXEL_SIZE * ICON_SCALE_FACTOR) / Math.max(scale, MIN_SCALE);
        if (mowerIcon != null && mowerIcon.getWidth(null) > 0 && mowerIcon.getHeight(null) > 0) {
            drawIcon(g2d, worldSize);
        } else {
@@ -97,10 +121,14 @@
        double iconHeight = mowerIcon.getHeight(null);
        double maxSide = Math.max(iconWidth, iconHeight);
        double scaleFactor = worldSize / Math.max(maxSide, MIN_SCALE);
        double rotationRadians = Math.toRadians(-headingDegrees);
        AffineTransform original = g2d.getTransform();
        AffineTransform transformed = new AffineTransform(original);
        transformed.translate(position.x, position.y);
        if (rotationRadians != 0.0) {
            transformed.rotate(rotationRadians);
        }
        transformed.scale(scaleFactor, scaleFactor);
        transformed.translate(-iconWidth / 2.0, -iconHeight / 2.0);
        g2d.setTransform(transformed);
@@ -118,6 +146,15 @@
        g2d.fill(fallbackShape);
        g2d.setColor(Color.WHITE);
        g2d.draw(fallbackShape);
    double rotationRadians = Math.toRadians(-headingDegrees);
    double lineLength = radius;
    double dx = lineLength * Math.sin(rotationRadians);
    double dy = lineLength * Math.cos(rotationRadians);
    g2d.drawLine(
        (int) Math.round(position.x),
        (int) Math.round(position.y),
        (int) Math.round(position.x + dx),
        (int) Math.round(position.y + dy));
        g2d.setColor(original);
    }
@@ -137,7 +174,7 @@
        if (!positionValid) {
            return Double.NaN;
        }
        double worldSize = ICON_PIXEL_SIZE / Math.max(scale, MIN_SCALE);
        double worldSize = (ICON_PIXEL_SIZE * ICON_SCALE_FACTOR) / Math.max(scale, MIN_SCALE);
        return worldSize / 2.0;
    }
}